Get-WMIobject win32_ntlogevent - Newest 3 events - powershell

Is there a way to pull the most recent 3 error events from the System event log using Get-WMIObject and the win32_ntlogevent class?
$log = Get-WMIobject -ComputerName $server -Credential $cred -class win32_ntlogevent -filter "(logfile='system') AND (type='error')"
I know that Get-EventLog has a -Newest option but I don't see anything like that with WMI

Figured it out
$log | sort TimeGenerated | select -last 3

Don't use WMI for this. Your approach will retrieve all error events from the remote host (which could take quite some time), and then discard all but the latest 3 once you have everything on the local host. Use Get-EventLog and do the filtering at the source:
Get-EventLog -LogName 'System' -EntryType 'Error' -Newest 3

I don't think Wmi query supports limiting the results.
If you are desperate to use your command here is a most inefficient way of getting your expected output -
Get-WMIobject win32_ntlogevent -filter "(logfile='system') AND (type='error')" | select -first 3
Cheers,
G

Get-EventLog -LogName 'System' -EntryType 'Error' -Newest 3
WMI is the far more efficient way, and it returns the log name
$dt = $cdt = Get-Date;$CUmonth = (get-date).adddays(-30);$eventId = Get-EventLog -ComputerName $SystemlogFqdn -LogName 'System' -EntryType 'Error','Warning' -After $CUmonth;"GetMethod: $((New-TimeSpan $dt ($dt = get-date)).totalseconds)"
GetMethod: 163.585552
$dt = $cdt = Get-Date;PS C:\Users\User> $CUmonth = (get-date).adddays(-30);PS C:\Users\User> $eventID = Get-WmiObject Win32_NTLogEvent -ComputerName $SystemlogFqdn -filter "(logfile='system' AND Type <> 'Information' AND TimeWritten >= '$CUmonth')";PS C:\Users\User> "WMIMethod: $((New-TimeSpan $dt ($dt = get-date)).totalseconds)"
WMIMethod: 63.49941

Related

Get the last 10 events in Eventlog(Application, Secuirty, System) in PowerShell

I am trying to get the the last 10 events in the «EventLog» logs «Application», «Security» and «System» parallelly. I get an error with this message:
Get-EventLog : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'LogName'"
when running the script. The script works when running with only the logname "Application".
Get-Eventlog -Newest 10 -LogName "Application","Security","System"
"Application","Security","System" | ForEach-Object {
Get-Eventlog -Newest 10 -LogName $_
}
That will get you the 10 most recent events in each log. If you want the 10 most recent events of all three logs taken together, you will need to do this:
"Application","Security","System" | ForEach-Object {
Get-Eventlog -Newest 10 -LogName $_
} | Sort-Object -Property Time -Descending | Select-Object -First 10
You can't do it the way you are trying, as -LogName requires a string and you are passing an array.
You could accomplish your task by piping an array into a ForEach-Object and going through the logs one at a time. The %{} is an alias for ForEach-Object
"Application","Security","System" | %{Get-Eventlog -Newest 10 -LogName $_}
Get-eventlog has been replaced by get-winevent. You'd still have to use foreach to get 10 of each. Grouping by logname instead of providername might be less annoying.
echo Application,Security,System | % { get-winevent $_ -maxevents 10 } |
ft -groupby logname

Add Filter to Get-EventLog (server side), returning only newest N records

Is there any way to filter event log entries using PowerShell before retrieving them?
i.e.
Instead of:
[string[]]$IgnoredSources = 'SomeValue','SomeOtherValue'
Get-Eventlog -LogName $MyLog -ComputerName $MyComputer `
| ?{$IgnoredSources -notcontains $_.Source} `
| Sort-Object TimeGenerated -Descending `
| Select-Object -First 10
Something like:
Get-Eventlog -LogName $MyLog -ComputerName $MyComputer `
-Filter {(Source -ne 'SomeValue') -and (Source -ne 'SomeOtherValue')} `
-Newest 10
More info
I'm aware that I can add a where-object statement to filter the results pulled back; but that's less efficient than filtering on the server side, and means that commands such as -Newest 100 won't necessarily return 100 results once filtered (i.e. I'd have to pull back the entire event log to ensure that I'd get the latest
I'm also aware that for dates this is possible via the -After and -Before attributes, and that it's possible to provide a list of -Username's and -Source's to limit to those. However if I want to exclude 1 source, or filter on a range of event ids, there seems to be no way at present.
I've looked into using Get-WmiObject instead of Get-EventLog, but whilst this allows the filtering to take place server side, I couldn't determine a way to limit the number of results returned (i.e. returned to my machine before sorting then using select-object's -first to then filter down the results).
Get-WmiObject Win32_NTLogEvent -ComputerName $MyComputer `
-filter "(logfile='$MyLog') and (sourcename != 'SomeValue') and (sourcename != 'SomeOtherValue') " `
| Sort-Object TimeGenerated -Descending `
| Select-Object -First 10
How about Get-WinEvent? Something like this:
Get-WinEvent -ComputerName $MyComputer -MaxEvents 100 -FilterHashtable #{
LogName=$MyLog;
ID=$MyID;
<# etc. #>
}

Extract dates and calculate difference

I have two different objects.
One would be an WMI Event Log and the other a WMI Management object.
How would I extract the dates from these variable and find a time difference?
Edit:
$start = Get-WmiObject Win32_Process -Filter "commandline like '%something%'" -ComputerName $server | %{ $_.ConvertToDateTime($_.CreationDate) }
$end = Get-WMIObject -ComputerName $server -Query "SELECT TimeGenerated FROM Win32_NTLogEvent WHERE LogFile='Application' AND CategoryString = 'Server Startup'" | Select TimeGenerated -First 1
Sample output of the two:
1/20/2016 3:55:48 PM
#{TimeGenerated=20160120210057.000000-000}
It is necessary to use the -Query for the end time, as the event is distinguished by the Category.
I'm currently getting the following error when trying to subtract the two.
Cannot find an overload for "op_Subtraction" and the argument count: "2".
You can use the subtraction operator (-):
$diff = $end.'Eventlog Time: ' - $start.'ABCD Start Time'
Or pass the values as arguments to New-TimeSpan:
$diff = New-TimeSpan -Start $start.'ABCD Start Time' -End $end.'Eventlog Time: '
It seems like you attempt to "optimize" the property names for displaying it later - I would recommend against that, and simply store the DateTime object in the variable by itself:
$start = Get-WmiObject Win32_Process -Filter "commandline like '%something%'" -ComputerName $server | Select -First 1 |%{ $_.ConvertToDateTime($_.CreationDate) }
$end = Get-EventLog System -Newest 1 -ComputerName $server -Source Microsoft-Windows-Winlogon |Select -ExpandProperty TimeGenerated
$diff = $end - $start

Start time of a process running on remote machine using powershell

I want to get the start time of a process running on remote machine using powershell.
On my local computer I get it simply by using get-process $processname | select StartTime.
I tried using get-process $processname -computername $server1 | select StartTime but this is returning me nothing.
Please suggest any better way.
Using WMI. This code return start time of powershell.exe process:
$a = gwmi win32_process -computername $server1| ? { $_.name -eq "powershell.exe" }
$a | % { $_.ConvertToDateTime( $_.CreationDate )}
PS> $StartTime= #{n='StartTime';e={$_.ConvertToDateTime($_.CreationDate)}}
PS> gwmi win32_process -cn $server1 -filter "Name='$processname' AND CreationDate IS NOT NULL" | select Name,$StartTime

Calling Get-WMIObject on multiple computers selected via Get-ADComputer

I'm trying to call Get-WMIObject (gwmi) on multiple computers selected via Get-ADComputer as a background job.
My first attempt was
$job = Get-ADComputer -filter "name -like '*t90*'" | % { gwmi -computername $_.name -query "select name,username from win32_computersystem" -asjob -throttlelimit 10 }
However, since I'm calling gwmi once for each computer object returned, hundreds of background jobs are created, and I don't believe they're collectively heeding the ThrottleLimit.
Am I doing this right?
I know that gwmi can also accept an array for the computername attribute, as so:
$job = gwmi -computername "computer1","computer2","computer3" -query "select * from win32_computersystem" -asjob -throttlelimit 10
Doing it this way results in a single job rather than hundreds, since gwmi is only called once. Is that the way I should be doing it? And, if so, how do I feed the output of Get-ADComputer to gwmi as an array?
Thanks!
First get all computer names and pass them to the computerName parameter:
$cn = Get-ADComputer -filter "name -like '*t90*'" | select -expand name
$job = gwmi -computername $cn -query "select name,username from win32_computersystem" -asjob -throttlelimit 10