Deal with Date Time in PowerShell - powershell

I've written a pretty nifty PowerShell script that works with VMware PowerCLI to clone a couple of VMs off to a second storage device and then automatically delete them when they reach a certain age. It seems to work great until it gets to the end/beginning of the month, then the approach I used for date time seems to fail and all clones are deleted unexpectedly. Rather than include the entire script, here are the pieces that matter.
First, when the clones are created I am using the following code..
$vmdatestamp = (Get-Date).tostring('yyyyMMdd-HHmmss')
new-vm -Name $VM-$vmdatestamp -VM $VM -Datastore $CPFlag -vmhost host.domain.local -Location 'Regular Clone'
This variable ends up creating a VM clone that is named something like "VMName-20200214-040022" in the case that the date is Feb 14th, 2020 and the variable captured 4 AM and 00 Min and 22 seconds.
Then later on in the script there is a cleanup section that lists these cloned VMs and checks the date. The objective is to run a delete command if the clone is older than 3 days. So there is a foreach loop that runs off of all VMs found within a particular folder, "Regular Clone". $vmls is the var within the loop for each VM found. Here is the code I am using to check the dates and delete older than 3 days.
#Grab matched string and doctor it to only look at 8 digit date.
$var1 = $vmls.name
$var2 = $var1 -split '-' | Select-String '\d{8}'
$var3 = $var2 -replace '(?S)'
#Grab todays date in the same 8 digit format then subtract to compare variance. How old is the clone?
$CompareDate = (Get-Date).tostring('yyyyMMdd')
$var4 = $CompareDate - $var3
#If clone is older than 3 days, delete it. Turn this knob based on your requirements.
if($var4 -gt '3') {
So this last "if" statement that checks $var4 is greater than 3 is where the source of my problem is. I don't think the script is smart enough to figure out if for example today is the 1st, how minus '-' works. Anyone have a suggestion on how to better deal with this?
Regards,
Adam Tyler

Powershell has a great deal of flexibility in dealing with dates and times using the [datetime] type. There is probably another answer to this somewhere out there, and I'll search for it later, but here are some basics.
When you read in your filenames, which I am assuming are in 'VMName-yyyyMMdd-HHmmss' format, you can turn that into a PowerShell [datetime] object like so (Thanks to this post for the info on [datetime]::parseexact):
[string]$VMFileName = #load $VMFileName variable with the name of your VM file somehow
$VMFNSplit = $VMFileName -split '-'
$FileDateStamp = [datetime]::ParseExact("$($VMFNSplit[-2])-$($VMFNSplit[-1])",'yyyyMMdd-HHmmss',$null)
EDIT:
Tested the above, and got this:
PS> $VMFileName = 'VMName-20200222-043322'
PS> $VMFNSplit = $VMFileName -split '-'
PS> $VMFNSplit[-2]
20200222
PS> $VMFNSplit[-1]
043322
PS> "$($VMFNSplit[-2])-$($VMFNSplit[-1])"
20200222-043322
PS> $FileDateStamp = [datetime]::ParseExact("$($VMFNSplit[-2])-$($VMFNSplit[-1])",'yyyyMMdd-HHmmss',$null)
PS> $FileDateStamp
Saturday, February 22, 2020 4:33:22 AM
Once you have your file date/time stamp in a [datetime], you can use the built in methods to add/subtract your intervals, like this:
#If clone is older than 3 days, delete it. Turn this knob based on your requirements.
$TooOld = (Get-Date).AddDays(-3)
If ($FileDateStamp -lt $TooOld) {#Delete it}
Hope this helps!

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
}
}

PowerShell - Comparing File.LastWriteTimeUtc

I'm trying to write a script that will copy a file to a second location, when the file changes.
For that I'm using an if statement like this:
if (
(Get-ChildItem C:\folder2\file).LastWriteTimeUtc -ge (Get-ChildItem C:\folder1\file).LastWriteTimeUtc
)
{exit}
else
{#execute}
Right now the files are exactly the same and if I run
(Get-ChildItem C:\folder2\file).LastWriteTimeUtc
the result for both is
Friday, 15. April 2022 23:32:09
My issue is that both LastWriteTimes appear to be the same and the script shouldn't do anything, but it does. And the reason for that is, that even though both values seem to be the same they are not and comparing them with "-eq" returns "False".
I'm using PowerShell 5.1
Thanks for all the replies. I'm sorry if I wasn't as specific as I should have been. But because of them I found an answer that should work for me.
First I get both dates as ticks and convert them to strings
$datef2 = (Get-ChildItem C:\folder2\file).LastWriteTimeUtc.Ticks.ToString()
$datef1 = (Get-ChildItem C:\folder1\file).LastWriteTimeUtc.Ticks.ToString()
then I replace the last 7 digits with 0 (which is everything small than a second) and compare them
($datef2.Substring(0,$datecb.Length-7) + "0000000") -ge ($datef1.Substring(0,$datenx.Length-7) + "0000000")
Might not be the most elegant solution but it gives the if statement the correct values.

Hyper-V: Make a script that pulls last 6 digits of computer name, converts it to hex, then inserts as VM's MAC address (Last 8 digits)

I am currently using Hyper-V and I want to change the static MAC Address into the last 6 digits of the computer name. MAC Addresses are in Hex. The computer name is a combination of random letters and random numbers generated by another script.
So far I have this:
$lastSixChar = $env:COMPUTERNAME.Substring($env:COMPUTERNAME.Length - 6)
$convertHex = $test | Format-Hex
This simply takes the name of the computer and converts it into hex. I'm not really sure if this is the smartest way to do this for actually pulling the hex, but at least it prints the correct number. I don't really know how I'm supposed to go about using the information I pulled and putting it into the last 8 digits of the MAC in Hyper-V.
Anything helps! Thanks
Edit:
Found this: Set-VMNetworkAdapter -VMName SRV01 -StaticMacAddress “00112233445566"
the code you posted doesn't seem to make hex strings. so the following does that. [grin] since you did not post how to make the 1st two MAC address blocks, and have not responded to comments on that subject, i left that out.
i don't have any of the VM stuff, so i will leave your addition to your Question as the answer for that part of the problem.
# fake reading in a text file
# in real life, use Get-Content
# or use one of the AD or VM cmdlets and filter out all but the system name values
$SystemNameList = #'
pc1234567890
pc2a3s4d5f6g
pc3z4x5c6v7b
'# -split [System.Environment]::NewLine
$Results = foreach ($SNL_Item in $SystemNameList)
{
$HexList = #()
# the "-replace" strips out all but the last 6 chars in the string
foreach ($SB_Item in ($SNL_Item -replace '.+(.{6})$', '$1').ToCharArray())
{
# this uses the string format operator to convert the int to hex
$HexList += '{0:x0}' -f [int]$SB_Item
}
$HexList -join '-'
}
$Results
output ...
35-36-37-38-39-30
34-64-35-66-36-67
35-63-36-76-37-62

How to search a pattern in last 10 minutes of log using a powershell script

I am trying to make a log file monitor in Powershell. The requirement is to search a pattern in most recent (last 10 minutes log prints) in a log file using Powershell.
The format of log file is as follows:
20/04/2018 23:15:28: some information
20/04/2018 23:16:28: some information
20/04/2018 23:17:28: some information
:
20/04/2018 23:55:28: some information
20/04/2018 23:56:28: some information
So for example the script runs at 23:58 then it should search a pattern in log prints between '20/04/2018 23:48' and '20/04/2018 23:48' only.
Please advise. Thanks
You can always get the last few entries, say 10, from a text file like this:
Get-Content .\data.txt -Tail 10
Of course, this may not be from the last 10 minutes. Here is one option to do that:
Get-Content .\data.txt |
ForEach-Object {$threshold = (Get-Date).AddMinutes(-10)}{
if($_ -match "^(?<timestamp>(\d{2}/){2}\d{4} (\d{2}:){2}\d{2}):.*$")
{
if((Get-Date $Matches.timestamp) -gt $threshold)
{
$_
}
}
}
Of course, the pattern match will work for both mm/dd/yyyy and dd/mm/yyyy date formats as the structure is the same. However, you may get difficulties with Get-Date parsing the pattern if the file uses the opposite to your system. For example, the format in your example would work fine in the UK (dd/mm/yyyy), but will likely fail in the USA (mm/dd/yyyy) - I've not tested it, just warning based on previous issues with dates.

Powershell - adding multiple Get-Date commands into variable

So I am trying to get the date 3 months back using the Powershell command Get-Date. However, when I try to add multiple get-dates in one line it errors out or doesn't give me the results I'm looking for.
The End result I'm trying to get is $checkDate = 6-7-2016
I've tried this, but it doesn't really work:
$checkDate = (Get-Date).month -3 "-" (Get-Date).day "-" (Get-Date).year
Any ideas on how to accomplish this? I'm newer to Powershell and not exactly sure how to concatenate properly.
I'm using PS 4.0
What you are trying to do is format a calculated date. So let's start with calculating the date:
(Get-Date).AddMonths(-3)
That gets you today's date minus 3 months. Next you want to format it in a specific manner. That being Month-Day-Year. That can be done as such:
(Get-Date).AddMonths(-3).ToString("M-d-yyyy")
That results in:
6-7-2016