Run a command in middle of Write-Host - powershell

I have a write-host line that I want to execute a command in the middle of, so the output will be inserted in the middle of the write-host string.
Basically I have a txt file that holds configuration data for a suite of scripts, one of the configurations is the format for dates and time. For example, there is a configuration for the year format which is 'YYYY' and it is written to $Year.
So what I would like to do is something like this:
Write-Host "The year is " Get-Date -Format $Year.ToLower()
What I expect to see on my screen when this is ran, is
The year is 2019
Now I know I can declare another variable with this logic and just have...
Write-Host "The year is $NewVariable"
...but I was hoping not to create another variable. This is a dumb-ed down example of my scrip, so I would be creating a lot of variables if I go this rout. Please note I am using .ToLower() to compensate for the user's input into the configuration text file.

In order to print the year of the Get-Date run this:
Write-Host "The year is $(Get-Date -Format yyyy)"
This way you will always get the year that is generated by Get-Date

This works fine....
$year = "2019"
Write-Host "The year is" (Get-Date -Format $Year.ToLower())

Related

PowerShell: Is there a way to search an specific word in a file's name and open the file if it finds it?

I haven't been able to figure out how to make this task that sounds simple in PowerShell.
I am trying to make a powershell variable that represents a file only using a part of it's name, since the rest of the name changes periodically. This should represent a little better what is my intention.
#Each day the number changes except for the Name part.
Name1, Name2, Name3...
#Variable must be able to work regardless of the number it has since the Name part never changes.
$Variable: Volume\Folder\Name(X).exe
I'm sorry if i'm not explaining myself well enough.
I'll provide any aditional information that is needed.
Well, to me it seems to be two diiferent tasks at hand:
First your title suggests You are lokking for a way to check the filenames of files in a given directory i assume and run that file with the default filehandler (again i can only speculate)
# 1. task
$path="C:\myfolder\"
$mySearchKey="taxes"
$myItmes=Get-ChildItem -Path $myPath
foreach($item in $myItems){
if($item.name -like "*$mySearchkey*"){
$matchingPath=$path+$item.name
Invoke-Item $matchingPath
}
}
Secondly In your description and the code example the question seems to be evolving around the idea to create dynamic variables for filenames most likely for the files we where opening before, based on the day in relation to a start date:
#2. task
$afileName="Marry"
$startdate= Get-Date "2022-12-06"
$todays= get-date
$numberOfDays = New-TimeSpan -Start $startdate -End $todays
$numberOfDays++ # since a differnce of 0 days means your in the 1. day
$newPath="Volume\Folder\"+$afileName+$numberOfDays+".exe"
But I yet have to figure out your end-game. How are the two coming together?
Run script where you want to search.
$all_files = ls
$filename = Read-Host "Enter File Name"
foreach ($item in $filename)
{
if ($item -match $filename)
{
Get-Content $item
}
}

Working with unusual date formats in Powershell?

I am working on a GUI-based Powershell tool to help users easily find out when their AD password is going to expire. Due to Covid restrictions, most users and not on-site and rely on VPN to connect to AD. A by-product of this is that many do not see the automatic pop-up in Windows to remind them of them to set a new password soon. Those that are on-site see the notification OK. It's a not a group-policy problem. The tool will be will be rolled-out in two different languages - one representing the 'mothership' (where is English is not normally spoken) and English for all other countries.
Some of the (mostly) Eastern European countries use a short date format that reads like 'd.M.yyyy.' - according to settings menu when one changes the 'Region' setting in Windows.
The tool calculates the difference between today and the expiry data and outputs the number of days to a text field. The actual expiry is display correctly in its own text field.
Some of the source code behind it all...
$thisUser = [Environment]::UserName
#make string
"net user " + $thisUser + " /domain"
#make cmd string
$fetch_net_user = "net user " + $thisUser + " /domain"
#execute command and store to variable
$net_user_data_array = Invoke-Expression $fetch_net_user
#Gets password expiry date (with header)
$password_expiry_with_header = $net_user_data_array[11]
#extracts only the date and assigns to new variable (the hours and minutes) can be ignored)
$password_expiry_as_string = $password_expiry_with_header.Split(' ')[-2]
# Home countries - works OK
try{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd.MM.yyyy', $null)
}
# Others - works OK
catch{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'dd/MM/yyyy', $null)
# where problem occurs
catch{
$password_expiry_as_dateTime = [datetime]::ParseExact($password_expiry_as_string, 'd.M.yyyy.', $null)
}
finally{
#show GUI error window...
}
#fetch date... converted to yesterday to fix an off-by-one bug!
$today = Get-Date
$rightNow = $today.AddDays(-1)
#calc days left
$daysRemaining = (New-TimeSpan -Start $rightNow -End $password_expiry_as_dateTime).Day
# some other code follows, manipulating date values etc. Works with most date formats.
When executed the script will throw several errors.
The first is...
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
Others will follow such as
You cannot call a method on a null-valued expression.
As the difference between today and the expiry date cannot be calulated.
Is there any easy fix for this? I'd rather avoid having to write a long list of 'if' statments for each country/culture. Thanks!
I'm sure the code could be a little bit more elegant, and that will be addressed in a later version. Right now, getting it to work some of the more obscure date formats is my priority.
Something else that I should stress is that this tool works in a 'read only' capacity. No 'Set-Item' commands are used.
Regards,
WL
You have 2 problems:
Multiple date formats used interchangeably
Trailing dots on some strings
The first problem can be solved by passing multiple format strings to ParseExact() - it'll try each in order until it successfully parses the input string (or reaches the end of the list):
[datetime]::ParseExact($password_expiry_as_string, [string[]]#('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)
The second problem can be solved by trimming trailing dots:
[datetime]::ParseExact($password_expiry_as_string.TrimEnd('.'), [string[]]#('dd.MM.yyyy', 'dd/MM/yyyy', 'dd.M.yyyy', 'd.M.yyyy'), $null, [System.Globalization.DateTimeStyles]::None)

Why do my DateTime objects behave differently?

I have a script that checks for certain logs between two times $startDate and $endDate using Search-UnifiedAuditLog where $startDate is found by checking a line in a .txt file and $endDate is the current time. I run this as shown below.
$startDate = Get-Content $logPath -Last 1
$startDate = [datetime]$startDate
$startDate = $startDate.AddHours(-1)
$endDate = (Get-Date)
This particular script is run every hour, so the time between $startDate and $endDate is two hours (due to the AddHours). If I check the value of these variables, they are indeed two hours apart. However, when I run the script, it goes through the previous 6 hours of logs. This makes me think it is assuming that $startDate is in UTC, and it is converting it to my time zone. Is this what it is doing, and if so, how can I get my script to only check for logs one hour before the time listed in my .txt document?
Turning my comment into an answer
You can check the .Kind property of the $startDate variable.
This property can be either Local, Utc or Unspecified. See DateTimeKind Enum.
In case of Unspecified, since .NET 2.0, "This instance of DateTime is assumed to be a UTC time, and the conversion is performed as if Kind were Utc." as stated in the docs

Exact date & time in subprogram with powershell

I'm new to powershell and I try to solve a problem I already managed to solve with batch scripting. I know how to set a variable and how to get the date with powershell. But I made a special subprogram for the exact date and time in batch and I don't know how to do that in powershell. Also I'm asking myself if there's an equivalent for %~dpn0 in powershell?
This are the parts of my batch script I want to use in powershell:
set pgm=%~n0
set log=%~dpn0.log
set csv=%~dpn0.csv
set dir=%~dp0users
set txt=%~n0.txt
set fix=%~dpn0.fix
call :loggy I "Program %pgm% started..."
:loggy
set welcomesev=%1
set welcometxt=%~2
set welcomeJJJJ=%date:~6,4%
set welcomeMM=%date:~3,2%
set welcomeDD=%date:~0,2%
set welcomeHR=%time:~0,2%
set welcomeMIN=%time:~3,2%
set welcomeSEC=%time:~6,2%
set welcomeDT=%welcomeJJJJ%.%welcomeMM%.%welcomeDD% %welcomeHR%:%welcomeMIN%:%welcomeSEC%
echo %welcomeDT% [%welcomesev%] %welcometxt% 1>>%log%
goto :EOF
Sorry for the many questions but I couldn't find anything with the search function.
Greetings
Does this function help you?
function Extract-CurrentDate{
$date = (Get-Date -Format d).ToString()
$time = (Get-Date -Format t).ToString()
Write-Host "$date $time"
}
Extract-CurrentDate
In generell you can use the Cmdlet Get-Date for you issue. It has many options, see this article. Moreover, you can format your output like this.

updating PS script to run daily exchange logs

i create this script
$VarDay = (Get-Date).day
$VarMonth = (Get-Date).month
get-messagetrackinglog -Recipients:haavarot-from#my-domain.co.il -EventID "FAIL" -Start "09/20/14" -End "09/23/14" | export-csv c:\MailboxStatistics-$VarMonth-$VarDay.csv -encoding "utf8"
to create CSV file with the date name for FAIL mails from mail box
its work fine
but the only problem i cant found is to way to make it run daily wit no need to edit the DATES in the Ps code
-i want it to sat auto run at 22:00 every day and make the log for the some day only for 7 days
in the 8 day i want it to delete the old and create a new one
i need to save only the last 7 days
and idea?
-Start and -End accepts [System.DateTime] so you can just use Get-Date and play with the days using AddDays()
Straight from MSDN. You could do something like this
$endDate = Get-Date # This is today
$startDate = (Get-Date).AddDays(-7) # This is 7 days ago
If you would feel more comfortable with just the date and drop the time you can use the .ToString() method to format the time. Note that the datetime object would be lost as this returns a string.
$endDate = (Get-Date).ToString("MM/dd/yy")
$startDate = ((Get-Date).AddDays(-7)).ToString("MM/dd/yy")
More information on formatting dates can be found here