We are attempting to do an audit on printing, and thought that PowerShell would be an excellent way to parse the Event Viewers of our computers to get out all of our ID numbers 307 out of Microsoft-Windows-PrintServices/Operational. However I can not find a way to filter only these events out of the Get-WinEvent. I am very new to PowerShell, and any help in the right direction would be of great use.

8 Spice ups

This is from Example 15 from the help file:

PS C:\>$events = Get-WinEvent -FilterHashTable @{ LogName = "Microsoft-Windows-Diagnostics-Performance/Operational"; StartTime = $date; ID = 100 }

Seems like that would be the best way to go. To see the full help file:

Get-Help Get-WinEvent -ShowWindow
4 Spice ups

Should be easy, this should work:

Get-WinEvent -LogName "Microsoft-Windows-PrintServices/Operational" | Where-Object { $_.Id = 307 }
2 Spice ups
help get-winevent -showwindow

-------------------------- EXAMPLE 13 --------------------------

PS C:>Get-WinEvent -Path “C:\Tracing\TraceLog.etl”, “c:\Logs\Windows PowerShell.evtx” -Oldest | Where-Object {$_.ID -eq “103”}

This example shows how to get the events from an event trace log file (.etl) and from a copy of the Windows PowerShell log file (.evtx) that was saved to a test directory.

You can combine multiple file types in a single command. Because the files contain the same type of .NET Framework object (an EventLogRecord object), you can use the same properties to filter them.

1 Spice up

Now what are the chances of that happening?

Cham & Bill: Filter Left, Format Right

CalvinAndHobbesHappyDance.jpg

3 Spice ups

Beat you two by MOMENTS!

2 Spice ups

Martin, when attempting to change those values, The logname and ID, to the desired log and event ID, it does not display anything. However, if I input

(Get-WinEvent -computername mb-it-02 -ListProvider microsoft-windows-printservice).events | Format-Table ID, description -auto

then I can clearly find IDs 307 in this log from my computer.

Chamele0n, when attempting use this code, I just seem to get errors :

PS C:> Get-WinEvent -LogName “Microsoft-Windows-PrintServices/Operational” | Where-Object { $_.Id = 307 }

Get-WinEvent : There is not an event log on the localhost computer that matches “Microsoft-Windows-PrintServices/Operational”.

At line:1 char:13

Get-WinEvent <<<< -LogName “Microsoft-Windows-PrintServices/Operational” | Where-Object { $_.Id = 307 }

CategoryInfo : ObjectNotFound: (Microsoft-Windo…ces/Operational:String) [Get-WinEvent], Exception

FullyQualifiedErrorId : NoMatchingLogsFound,Microsoft.PowerShell.Commands.GetWinEventCommand

PS C:> Get-WinEvent -listprovider “Microsoft-Windows-PrintServices/Operational” | Where-Object { $_.Id = 307 }

Get-WinEvent : There is not an event provider on the localhost computer that matches “Microsoft-Windows-PrintServices/Operational”.

At line:1 char:13

Get-WinEvent <<<< -listprovider “Microsoft-Windows-PrintServices/Operational” | Where-Object { $_.Id = 307 }

CategoryInfo : ObjectNotFound: (:slight_smile: [Get-WinEvent], Exception

FullyQualifiedErrorId : NoMatchingProvidersFound,Microsoft.PowerShell.Commands.GetWinEventCommand%uFEFF

Bill, I have not tried your method yet.

Bill, I’m not certain how they are finding the paths here. Should this be something that I am exporting? And is the combination to the PowerShell log file only so that you can at that point use the “Where-Object” command?

Okay, so after trying this again, it did seem to work for me, however I removed the start time and just grabbed the IDs. Thanks Martin!

2 Spice ups

Welcome, sorry I could jump in, busy at work :slight_smile:

No problem. Out of curiosity, do you happen to have any ideas about extending this to run on a list of computers? We’ve managed to get everything working out now on local and remote computers. However, if I attempt to use a variable, for example

PS C:\> $pods = "Computer1","Computer2","Computer3"
PS C:\> foreach ($pod in $pods)
>> {Get-WinEvent -ComputerName "$pods" -FilterHashTable @{ LogName = "Microsoft-Windows-PrintService/Operational" ; ID = "307"} | format-table id, message, machinename -auto >> "C:\PS Test\Test Log.txt"}

We get back

Get-WinEvent : The RPC server is unavailable
At line:2 char:14
+ {Get-WinEvent <<<<  -ComputerName "$pods" -FilterHashTable @{ LogName = "Microsoft-Windows-PrintService/Operational" ; ID = "307"} | format-table id, message, machinename -auto >> "C:\PS Test\Test Log.txt"}
    + CategoryInfo          : NotSpecified: (:) [Get-WinEvent], EventLogException
    + FullyQualifiedErrorId : System.Diagnostics.Eventing.Reader.EventLogException,Microsoft.PowerShell.Commands.GetWinEventCommand

For each computer. However, when we run the command without the variable and variable list it reports back the list of events.

Firstly, in your Get-WinEvent call, change $pods to $pod.

Next, turn on verbose output ($VerbosePreference = “Continue”). Then put a Write-Verbose statement in your code.

$pods = "mccoyb01","mccoyb02"
foreach ($pod in $pods) {
    Write-Verbose "Testing $pod"
    Get-WinEvent -ComputerName $pod -FilterHashTable @{ LogName = "Microsoft-Windows-Diagnostics-Performance/Operational"; ID = 100
    
} | format-table id, message, machinename -auto >> "C:\PS Test\Test Log.txt"}

This uses the sample event. Modify to test your event ID 307.

3 Spice ups

Thanks Bob! This seems to be working out perfectly.

Thanks Ken. Since Martin already has Best Answer, it you would mark my reply above as a Helpful Answer, I would appreciate it.

Note: -FilterHashTable does not work if the server is Windows 2008 (not R2). You will get a “parameter is incorrect” error.

Found this to be true on Powershell 2.0 and 3.0 so far - Where-Object is a lot slower but works.

Thanks for the update on this. Luckily the computers I was doing this for were all Windows 7. I’ve even managed to fiddle with this script and even get it printing out to a CSV for easier parsing.

1 Spice up
$pclist = (get-content "\\somepath\to\somepclistfile.txt")
foreach ($pc in $pclist) {
    Write-Verbose "Testing $pc"
    Get-WinEvent -ComputerName $pc -FilterHashTable @{ LogName = "Microsoft-Windows-PrintService/Operational"; ID = 307
} |  Export-CSV -Append -Path "\\somepath\to\output.csv" -Encoding Ascii -NoTypeInformation}

Roughly this is the updated version of the code that was worked out here. Worked beautifully as a way to audit print jobs per computer.

1 Spice up