Get a logfile for a specific date - powershell

I want to save in my computer "C:\logFiles" a specific date for logfile generated by program in another PC,
path that i will get from it the log file is "C:\Sut\Stat\03-2021.log"
Example : this file "C:\Sut\Stat\03-2021.Sutwin.log" contenant all the log of Mars month but i just want to get the log of last 7 Days from 19-03-2021 to 26-03-2021
I found this script in the internet but i doesn't work for me i need some help:
Example of the file .log in the photo attached:
Rest of image for the first screenshot :
my PC name : c01234
name of PC contenant log file : c06789
file that i will get from it the infos : 03-2021.Sutwin.log (exist in pc c06789)
i want to transfer the contents of just last 7 days in a folder in my PC c01234 with name Week11_LogFile
$log = "2015-05-09T06:39:34 Some information here
2015-05-09T06:40:34 Some information here
" -split "`n" | Where {$_.trim()}
#using max and min value for the example so all correct dates will comply
$upperLimit = [datetime]::MaxValue #replace with your own date
$lowerLimit = [datetime]::MinValue #replace with your own date
$log | foreach {
$dateAsText = ($_ -split '\s',2)[0]
try
{
$date = [datetime]::Parse($dateAsText)
if (($lowerLimit -lt $date) -and ($date -lt $upperLimit))
{
$_ #output the current item because it belongs to the requested time frame
}
}
catch [InvalidOperationException]
{
#date is malformed (maybe the line is empty or there is a typo), skip it
}
}

Based on your images, your log files look like simple tab-delimited files.
Assuming that's the case, this should work:
# Import the data as a tab-delimited file and add a DateTime column with a parsed value
$LogData = Import-Csv $Log -Delimiter "`t" |
Select-Object -Property *, #{n='DateTime';e={[datetime]::ParseExact($_.Date + $_.Time, 'dd. MMM yyHH:mm:ss', $null)}}
# Filter the data, drop the DateTime column, and write the output to a new tab-delimited file
$LogData | Where-Object { ($lowerLimit -lt $_.DateTime) -and ($_.DateTime -lt $upperLimit) } |
Select-Object -ExcludeProperty DateTime |
Export-Csv $OutputFile -Delimiter "`t"
The primary drawback here is that on Windows Powershell (v5.1 and below) you can only export the data quoted. On Powershell 7 and higher you can use -UseQuotes Never to prevent the fields from being double quote identified if that's important.
The only other drawback is that if these log files are huge then it will take a long time to import and process them. You may be able to improve performance by making the above a one-liner like so:
Import-Csv $Log -Delimiter "`t" |
Select-Object -Property *, #{n='DateTime';e={[datetime]::ParseExact($_.Date + $_.Time, 'dd. MMM yyHH:mm:ss', $null)}} |
Where-Object { ($lowerLimit -lt $_.DateTime) -and ($_.DateTime -lt $upperLimit) } |
Select-Object -ExcludeProperty DateTime |
Export-Csv $OutputFile -Delimiter "`t"
But if the log files are extremely large then you may run into unavoidable performance problems.

It's a shame your example of a line in the log file does not reveal the exact date format.
2015-05-09 could be yyyy-MM-dd or yyyy-dd-MM, so I'm guessing it's yyyy-MM-dd in below code..
# this is the UNC path where the log file is to be found
# you need permissions of course to read that file from the remote computer
$remotePath = '\\c06789\C$\Sut\Stat\03-2021.log' # or use the computers IP address instead of its name
$localPath = 'C:\logFiles\Week11_LogFile.log' # the output file
# set the start date for the week you are interested in
$startDate = Get-Date -Year 2021 -Month 3 -Day 19
# build an array of formatted dates for an entire week
$dates = for ($i = 0; $i -lt 7; $i++) { '{0:yyyy-MM-dd}' -f $startDate.AddDays($i) }
# create a regex string from that using an anchor '^' and the dates joined with regex OR '|'
$regex = '^({0})' -f ($dates -join '|')
# read the log file and select all lines starting with any of the dates in the regex
((Get-Content -Path $remotePath) | Select-String -Pattern $regex).Line | Set-Content -Path $localPath

Related

Datetime in PowerShell can't convert my Time

I'm writing a Script to compare two sets of timevalues and then calculate a exact time.
My problem is the calculation with timestamps. I import the times from a .csv-file. The times look like this:
08:37;
11:47;
12:11;
17:34;
etc.
I made a variable for the times so i always have the correct time from the correct line from the csv file.
My goal ist to calculate the time from one timestamp to another like this: 11:47 - 08:37 = 3:10
If i do this in my PowerShell Script an error occurs: The value "time=12:39" can not be converted to type "System.DateTime". Error: "The string was not recognized as a DateTime. An unknown word starts at index 1"
Is datetime wrong in this case? How can i make this work?
Thx for your help.
If this has to do with your previous question and the CSV actually looks like this:
name;prename;date;time
Gantz;Mario;09.02.;07:37
Gantz;Mario;09.02.;11:23
Gantz;Mario;09.02.;12:34
Gantz;Mario;09.02.;17:03
Then this should do it
# create two variables to hold the times parsed from the CSV, Initialize to $null
$current, $previous = $null
# load the csv and loop through the records
$result = Import-Csv -Path 'D:\Test\times.csv' -Delimiter ';' | ForEach-Object {
$current = [datetime]::ParseExact($_.time, 'HH:mm', $null)
if (!$previous) { $previous = $current }
# subtracting two DateTime objects results in a TimeStamp
$elapsed = $current - $previous
$previous = $current
# output the record with column 'elapsed' appended
$_ | Select-Object *, #{Name = 'elapsed'; Expression = {$elapsed.ToString()}}
}
# output on screen
$result | Format-Table -AutoSize
# output to new CSV file
$result | Export-Csv -Path 'D:\Test\times_and_intervals.csv' -Delimiter ';' -NoTypeInformation
Output on screen:
name prename date time elapsed
---- ------- ---- ---- -------
Gantz Mario 09.02. 07:37 00:00:00
Gantz Mario 09.02. 11:23 03:46:00
Gantz Mario 09.02. 12:34 01:11:00
Gantz Mario 09.02. 17:03 04:29:00
Now that I see you also have a 'date' column in there, you should include that in the conversion to [datetime] aswell:
# create two variables to hold the times parsed from the CSV, Initialize to $null
$current, $previous = $null
# load the csv and loop through the records
$result = Import-Csv -Path 'D:\Test\times.csv' -Delimiter ';' | ForEach-Object {
$completeDate = '{0}{1} {2}' -f $_.date, (Get-Date).Year, $_.time
$current = [datetime]::ParseExact($completeDate, 'dd.MM.yyyy HH:mm', $null)
if (!$previous) { $previous = $current }
# subtracting two DateTime objects results in a TimeStamp
$elapsed = $current - $previous
$previous = $current
# output the record with column 'elapsed' appended
$_ | Select-Object *, #{Name = 'elapsed'; Expression = {$elapsed.ToString()}}
}
# output on screen
$result | Format-Table -AutoSize
# output to new CSV file
$result | Export-Csv -Path 'D:\Test\times_and_intervals.csv' -Delimiter ';' -NoTypeInformation
You are getting the error because you are not specifying the values that you are importing as [datetime]
I have replicated the error where I just specified 2 time values and subtracted them:
$st = "08:37" $et = "11:47" $di = $st - $et Cannot convert value
"08:37" to type "System.Int32". Error: "Input string was not in a
correct format."
Solution:
Specify the values of each entry like so:
[datetime]$starttime = "08:37"
[datetime]$endtime = "11:47"
$diff = $endtime - $starttime
If you just want the time in minutes etc. you can enter $diff.Minutes respectively
Hope this works for you.

Copy altered CSV Data to new CSV

The whole point of this issue is going to be: How to copy data from one CSV to another without knowing/listing the headers of the original CSV.
The cmdlet I'm building is meant to convert a report from CSV to a spreadsheet eventually. And if I write the column headers to the code, each time somebody changes the report, the code will break and it would have to be updated.
The steps I would take right now:
# Import the Source CSV. Gonna pull data from this later.
$SourceCSV = Import-Csv -Path $reportSourceCSV -Delimiter ";"
# Remove NULL characters, white spaces and change comma separator to semicolon.
(Get-Content -Path $reportSourceCSV | Where-Object {-not [string]::IsNullOrWhiteSpace($PSItem)}).Replace('","',";") | Out-File -FilePath $TMP1
# Import the modified new temp CSV.
$Input = Import-Csv -Path $TMP1 -Delimiter ";"
# Take existing CSV file headers and append some new ones. Rename a long column name.
((($GetHeaders = foreach ($Header in $SourceCSV[0].PSObject.Properties.Name) {
"`"$Header`""
}) + '"column4"','"column5"','"column6"') -join ";").Replace("VerylongOldColumnName","ShortName") | Out-File -FilePath $TMP2
foreach ($Item in $Input) {
"`"$($Item.column1)`";`"$($Item.'column2')`";`"$($Item.column3)`"" | Out-File -FilePath $TMP2 -Append
}
$exportToXLSX = Import-Csv -Path $TMP2 -Delimiter ";" | Export-Excel -Path $Target -WorkSheetname "reportname" -TableName "tablename" -TableStyle Medium2 -FreezeTopRow -AutoSize -PassThru
$exportToXLSX.Save()
$exportToXLSX.Dispose()
Remove-Item -Path $TMP1, $TMP2
This works! But I don't want to create infinite amount of different reports and just as many different logic blocks to process all these reports.
So this is as far as I was able to get trying a more dynamic way of processing the report CSVs:
(Get-Content -Path $reportSourceCSV | Where-Object {-not [string]::IsNullOrWhiteSpace($PSItem)}).Replace('","',";") | Out-File -FilePath $TMP1
$import = Import-Csv -Path $TMP1 -Delimiter ";"
$headers = ($import[0].PSObject.Properties.Name).Replace("VerylongOldColumnName","ShortName")
$headers | Out-File -FilePath "C:\TEMP\test.csv"
foreach ($item in $import) {
for ($h = 0; $h -le ($headers).Count; $h++) {
$($item.$($headers[$h]))
}
}
Now, this works... kind of. If I run the script like this, it shows me the output I want, but I was NOT able to export this to CSV.
I added Export-Csv to this line: $($item.$($headers[$h])) so this particular line would look like this:
$($item.$($headers[$h])) | Export-Csv -Path $Output -Delimiter ";" -Append -NoTypeInformation
And this is the error I get:
Export-Csv : Cannot append CSV content to the following file: C:\TEMP\test.csv.
The appended object does not have a property that corresponds to the following
column: column1. To continue with mismatched properties, add the -Force parameter,
and then retry the command.
At line:11 char:36
+ ... ers[$h])) | Export-Csv -Path $Output -Delimiter ";" -Append -NoTypeIn ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (column1:String) [Export-Csv], InvalidOperationException
+ FullyQualifiedErrorId : CannotAppendCsvWithMismatchedPropertyNames,Microsoft.PowerShell.Commands.ExportCsvCommand
If I add -Force parameter, the output will be the headers and a bunch of empty lines.
As little as I understand, is that the output is for some reason a string? To my knowledge everything should be an object in PS, unless converted to string (Write-Host cmdlet being an exception). And I don't really know how to force the output back to being objects.
Edit: Added sample source CSV
"Plugin","Plugin Name","Family","Severity","IP Address","Protocol","Port","Exploit?","Repository","DNS Name","NetBIOS Name","Plugin Text","Synopsis","Description","Solution","See Also","Vulnerability Priority Rating","CVSS V3 Base Score","CVSS V3 Temporal Score","CVSS V3 Vector","CPE","CVE","Cross References","First Discovered","Last Observed","Vuln Publication Date","Patch Publication Date","Exploit Ease","Exploit Frameworks"
"65057","Insecure Windows Service Permissions","Windows","High","127.0.0.1","TCP","445","No","Individual Scan","computer.domain.tld","NetBIOS Name","Plugin Output:
Path : c:\program files (x86)\application\folder\service.exe
Used by services : application
File write allowed for groups : Users, Authenticated Users
Full control of directory allowed for groups : Users, Authenticated Users","At least one improperly configured Windows service may have a privilege escalation vulnerability.","At least one Windows service executable with insecure permissions was detected on the remote host. Services configured to use an executable with weak permissions are vulnerable to privilege escalation attacks.
An unprivileged user could modify or overwrite the executable with arbitrary code, which would be executed the next time the service is started. Depending on the user that the service runs as, this could result in privilege escalation.
This plugin checks if any of the following groups have permissions to modify executable files that are started by Windows services :
- Everyone
- Users
- Domain Users
- Authenticated Users","Ensure the groups listed above do not have permissions to modify or write service executables. Additionally, ensure these groups do not have Full Control permission to any directories that contain service executables.","http://www.nessus.org/u?e4e766b2","","8.4","","AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","cpe:/o:microsoft:windows","","","Jul 11, 2029 06:48:20 CEST","Jul 11, 2029 06:48:20 CEST","N/A","N/A","",""
Edit: I think I found another way how to accomplish this and looking at it, it looks I tried to overdo it quite a bit.
# Doing cleanup, changing delimiters, renaming that one known column. All in one line.
$importCSV = 'C:\TEMP\sourceReport.csv'
(Get-Content -Path $importCSV | Where-Object {-not [string]::IsNullOrWhiteSpace($PSItem)}).Replace('","','";"').Replace"VerylongOldColumnName","ShortName") | Out-File -FilePath C:\TEMP\tmp1.csv
# Adding additional columns and exporting it all to result CSV.
Import-Csv -Path C:\TEMP\tmp1.csv -Delimiter ";" | Select-Object *, "Column1", "Column2" | Export-Csv -Path C:\TEMP\result.csv -NoTypeInformation -Delimiter ";"
You should not simply replace , with ; because the fields actually contain commas as in ..Additionally, ensure these groups .. By replacing just like that, the field will get separated from the rest of its content and you'll end up with a mis-aligned csv.
The below approach will do what you want, leaving the structure of the csv file intact:
$importCSV = 'C:\TEMP\sourceReport.csv'
$exportCSV = 'C:\TEMP\result.csv'
$columnsToAdd = "Column1", "Column2"
# read the file as string array, not including empty lines
$content = Get-Content -Path $importCSV | Where-Object { $_ -match '\S' }
# replace the column header in the top line only
$content[0] = $content[0].Replace("VerylongOldColumnName", "ShortName")
# join the string array with newlines and convert that to an object with ConvertFrom-Csv
# add the columns to the object and export it using the semi-colon as delimiter
($content -join [Environment]::NewLine) | ConvertFrom-Csv |
Select-Object *, $columnsToAdd |
Export-Csv -Path $exportCSV -NoTypeInformation -Delimiter ";"

Need to extract 8 & 9 digit file numbers from 40,000 emails using PowerShell

I am attempting to extract 8 & 9 digit file numbers from 40,000 emails that have been saved as .txt files. The File numbers can appear any where in the email(s)...(it's not a standard form), but should always be 8 or 9 digits in length. The file numbers can also be formatted several different ways Like: xxx xx xxxx, xxx-xx-xxxx, xxxxxxxxx, 8 digit #'s: YY YYY YYY, YY-YYY-YYY, YYYYYYYY. I created a PowerShell script that reads the text file extracts the file numbers matching the said pattern and creates & saves them to a .csv file.
Problems: If there is any text proceeding the file# on the line, the script fails to grab the file #. It also grabs additional text (on the same line after the File #). I need only exact matches to the set patterns.
Solution does not need to be in PowerShell, If there is a better solution in vbscript I'm also open to that.
current script is below:
$Num = #()
$Num += Select-String -Path "$PSSCRIPTROOT\text.txt" -Pattern '\d{8}$|^\d{2}\s\d{3}\s\d{3}$|^\d{2}-\d{3}-\d{3}$'
$Num += Select-String -Path "$PSSCRIPTROOT\text.txt" -Pattern '\d{9}$|^\d{3}\s\d{2}\s\d{4}$|^\d{3}-\d{2}-\d{4}$'
ForEach ($Matches in $Num){
$Found = $Matches.ToString().Split(":")
$o = new-object PSObject
$o | add-member NoteProperty "FoundOnLine" $Found[2]
$o | add-member NoteProperty "Number" $Found[3]
$o | export-csv "$PSscriptroot\FoundNumbers.csv" -notypeinformation -Append
Write-Output $o
PLEASE HELP!
This should do the trick actually ...
$File = "$PSSCRIPTROOT\text.txt"
$Pattern = '\d\d(\s|-)*\d(\s|-)*\d(\s|-)*\d{4,5}'
Select-String -Path $File -Pattern $Pattern -AllMatches |
Select-Object -ExpandProperty Matches |
Select-Object -ExpandProperty Value

Powershell variable in file name

Everyday a file is being saved with the current date in format testDDMMYYY.csv for an example test24112017.csv.
I need to open the current day's file with Powershell, however, I haven't found a way for it to work with variables.
#Date (24112017)
[String]$a=(Get-Date).ToShortDateString() | Foreach-Object {$_ -replace "\.", ""}
#Open the file called test24112017
[int] $S1=Get-Content "D:\test$($a).csv" -Tail 1 | Foreach-Object {$_ -replace "`"", ""} | ForEach-Object{$_.Split(",")[1]} | write-host
How can I get that variable working inside that path?
Do not use (Get-Date).ToShortDateString() | Foreach-Object {$_ -replace "\.", ""}, just use Get-Date -Format 'ddMMyyyy' to format the date the way you want :
Get-Content "D:\test$(Get-Date -Format 'ddMMyyyy').csv" -Tail 1
Formatting Dates and Times
Hmm aren't you over-complicating things a bit?
First of all,
(Get-Date).ToShortDateString() doesn't give me 24112017 but 24-11-2017.
So i'm guessing we have different regional settings, what part of the world are you from?
Have you printed out $a? What does it give you?
I would go for a different approach. Since your filename is literally always newer than the previous one (because it holds a date).
I would just sort on the Name and select the first one (aka the newest file).
$newestfile = Get-ChildItem c:\temp | Sort-Object Name -Desc | select * -First 1
Now go do whatever you want with your latest file.
get-content $newestfile.fullname

Retrieve data from last line in vmware.log file?

I currently have a script that retrieves the last modified date of the .vmx in a VM's datastore in vCenter. I need to make changes to instead use and display the last date in the vmware.log file (located in the same datastore as the .vmx)
I'm not sure how to grab that line and convert it to a XX/XX/XXXX format. In the log file, it shows it as Dec 23 10 for example. If this is not possible, no worries. I just need to pull the last line in the log file and export it to a .csv file. Below is my current code:
add-pssnapin VMware.VimAutomation.Core
# ---------- Only modify the fields in this area -------------
$vCenter = 'qlab-copsmgr' #name of the vCenter
$dataCenter = 'Fly-away Kit' #name of the DataCenter
$outputFile = $vCenter + '-LastDateUsed.csv' #desired output file name
# ---------- No modification is needed in the below code. Do not edit -------------
$columnName = "Name,DataStore,Date Last Used" | Out-File .\$OutputFile -Encoding ascii
Connect-VIServer $vCenter -WarningAction SilentlyContinue
$vmList = Get-VM | where { $_.PowerState -eq “PoweredOff”} | select Name
$vmList = $vmList -replace 'Name : ', '' -replace '#{Name=', '' -replace '}', ''
ForEach ($VM in $vmList)
{
# Get configuration and path to vmx file
$VMconfig = Get-VM $VM | Get-View | select config
$VMXpath = $VMconfig.config.files.VMpathName
# Remove and/or replace unwanted strings
$VMXpath = $VMXpath -replace '\[','' -replace '\] ','\' -replace '#{Filename=','/' -replace '}','' -replace '/','\'
# List the vmx file in the datastore
$VMXinfo = ls vmstores:\$VCenter#443\$DataCenter\$VMXpath | Where {$_.LastWriteTime} | select -first 1 | select FolderPath, LastWriteTime
# Remove and/or replace unwanted strings
$VMXinfo = $VMXinfo -replace 'DatastoreFullPath=', '' -replace '#{', '' -replace '}', '' -replace ';', ',' -replace 'LastWriteTime=', ''
# Output vmx information to .csv file
$output = $VM + ', ' + $VMXinfo
$output
echo $output >> $OutputFile
}
I also needed to pull the last event from the vmware.log file in order to backtrack the power off time for VMs where there is no vCenter event history. I looked at file timestamps but found that some VM processes and possibly backup solutions can make them useless.
I tried reading the file in place but ran into issues with the PSDrive type not supporting Get-Content in place. So for better or worse for my solution I started with one of LucD's scripts - the 'Retrieve the logs' script from http://www.lucd.info/2011/02/27/virtual-machine-logging/ which pulls a VMs vmware.log file and copies it to local storage. I then modified it to copy the vmware.log file to a local temp folder, read the last line from the file before deleting the file and return the last line of the log as a PS object.
Note, this is slow and I'm sure my hacks to LucD's script are not elegant, but it does work and I hope if helps someone.
Note: This converts the time value from the log to a PS date object by simple piping the string timestamp from the file into Get-Date. I've read that this does not work as expected for non-US date formatting. For those outside of the US you might want to look into this or just pass the raw timestamp string from the log instead of converting it.
#Examples:
#$lastEventTime = (Get-VM -Name "SomeVM" | Get-VMLogLastEvent).EventTime
#$lastEventTime = Get-VMLogLastEvent -VM "SomeVM" -Path "C:\alternatetemp\"
function Get-VMLogLastEvent{
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)][PSObject[]]$VM,
[string]$Path=$env:TEMP
)
process{
$report = #()
foreach($obj in $VM){
if($obj.GetType().Name -eq "string"){
$obj = Get-VM -Name $obj
}
$logpath = ($obj.ExtensionData.LayoutEx.File | ?{$_.Name -like "*/vmware.log"}).Name
$dsName = $logPath.Split(']')[0].Trim('[')
$vmPath = $logPath.Split(']')[1].Trim(' ')
$ds = Get-Datastore -Name $dsName
$drvName = "MyDS" + (Get-Random)
$localLog = $Path + "\" + $obj.Name + ".vmware.log"
New-PSDrive -Location $ds -Name $drvName -PSProvider VimDatastore -Root '\' | Out-Null
Copy-DatastoreItem -Item ($drvName + ":" + $vmPath) -Destination $localLog -Force:$true
Remove-PSDrive -Name $drvName -Confirm:$false
$lastEvent = Get-Content -Path $localLog -Tail 1
Remove-Item -Path $localLog -Confirm:$false
$row = "" | Select VM, EventType, Event, EventTime
$row.VM = $obj.Name
($row.EventTime, $row.EventType, $row.Event) = $lastEvent.Split("|")
$row.EventTime = $row.EventTime | Get-Date
$report += $row
}
$report
}
}
That should cover your request, but to expound further on why I needed the detail, which reading between the lines may also benefit you, I'll continue.
I inherited hundreds of legacy VMs that have been powered off from various past acquisitions and divestitures and many of which have been moved between vCenter instances losing all event log detail. When I started my cleanup effort in just one datacenter I had over 60TB of powered off VMs. With the legacy nature of these there was also no detail available on who owned or had any knowledge of these old VMs.
For this I hacked another script I found, also from LucD here: https://communities.vmware.com/thread/540397.
This will take in all the powered off VMs, attempt to determine the time powered off via vCenter event history. I modified it to fall back to the above Get-VMLogLastEvent function to get the final poweroff time of the VM if event log detail is not available.
Error catching could be improved - this will error on VMs where for one reason or another there is no vmware.log file. But quick and dirty I've found this to work and provides the detail on what I need for over 90%.
Again this relies on the above function and for me at least the errors just fail through passing through null values. One could probably remove the errors by adding a check for vmware.log existance before attempting to copy it though this would add a touch more latency in execution due to the slow PSDrive interface to datastores.
$Report = #()
$VMs = Get-VM | Where {$_.PowerState -eq "PoweredOff"}
$Datastores = Get-Datastore | Select Name, Id
$PowerOffEvents = Get-VIEvent -Entity $VMs -MaxSamples ([int]::MaxValue) | where {$_ -is [VMware.Vim.VmPoweredOffEvent]} | Group-Object -Property {$_.Vm.Name}
foreach ($VM in $VMs) {
$lastPO = ($PowerOffEvents | Where { $_.Group[0].Vm.Vm -eq $VM.Id }).Group | Sort-Object -Property CreatedTime -Descending | Select -First 1
$lastLogTime = "";
# If no event log detail, revert to vmware.log last entry which takes more time...
if (($lastPO.PoweredOffTime -eq "") -or ($lastPO.PoweredOffTime -eq $null)){
$lastLogTime = (Get-VMLogLastEvent -VM $VM).EventTime
}
$row = "" | select VMName,Powerstate,OS,Host,Cluster,Datastore,NumCPU,MemMb,DiskGb,PoweredOffTime,PoweredOffBy,LastLogTime
$row.VMName = $vm.Name
$row.Powerstate = $vm.Powerstate
$row.OS = $vm.Guest.OSFullName
$row.Host = $vm.VMHost.name
$row.Cluster = $vm.VMHost.Parent.Name
$row.Datastore = $Datastores | Where{$_.Id -eq ($vm.DatastoreIdList | select -First 1)} | Select -ExpandProperty Name
$row.NumCPU = $vm.NumCPU
$row.MemMb = $vm.MemoryMB
$row.DiskGb = Get-HardDisk -VM $vm | Measure-Object -Property CapacityGB -Sum | select -ExpandProperty Sum
$row.PoweredOffTime = $lastPO.CreatedTime
$row.PoweredOffBy = $lastPO.UserName
$row.LastLogTime = $lastLogTime
$report += $row
}
# Output to screen
$report | Sort Cluster, Host, VMName | Select VMName, Cluster, Host, NumCPU, MemMb, #{N='DiskGb';E={[math]::Round($_.DiskGb,2)}}, PoweredOffTime, PoweredOffBy | ft -a
# Output to CSV - change path/filename as appropriate
$report | Sort Cluster, Host, VMName | Export-Csv -Path "output\Powered_Off_VMs_Report.csv" -NoTypeInformation -UseCulture
Cheers!
I pray this pays back some of the karma I've used.
Meyeaard
I have made a script that checks line by line and if string is found changes it to desired format
#example input you can use get-content PATH to txt or any file and assign it to $lines variable
$lines = #"
ernfoewnfnsf
ernfoewnfnsf
Dec 23 10 sgdsgdfgsdadasd
"# -split "\r\n"
#checks line by line and if find anything that maches start of the line, one Big letter two small, space, two digits, space, two digits, space
$lines | ForEach-Object{
if ($_ -match "^[A-Z][a-z]{2}\s\d{2}\s\d{2}\s")
{
$match = [convert]::ToDateTime($matches[0])
$_ -replace $matches[0], "$($match.ToShortDateString()) " | out-file { PATH } -APPEND
}
else
{
$_ | out-file { PATH } -APPEND
}
}
just change {PATH} with a filenamePAth and this should work for you