Summary: Windows PowerShell MVP, Jonathan Medd, provides expert commentary for 2012 Scripting Games Beginner Event 9.
Microsoft Scripting Guy, Ed Wilson, is here. Jonathan Medd is the expert commentator for Beginner Event 9.
Jonathan has been working with IT infrastructure products since 1997. A few years ago, he discovered Windows PowerShell, and he now cohosts the Get-Scripting PowerShell podcast. Since April 2010, he has been a Microsoft MVP for Windows PowerShell, and in 2011 was honored as a VMware vExpert. He is co-author of VMware vSphere PowerCLI Reference.
Wherever possible, when you are working with the Windows PowerShell pipeline, it is beneficial to carry out filtering as close to the left side of the set of commands as possible. Consequently, it is always worth checking out the first cmdlet in the pipeline to see if it has built-in possibilities for filtering, rather than having to pipe the results of the cmdlet into Where-Object and carrying out the filtering there.
In Event 9, we are using the Get-EventLog cmdlet, so it is worth examining the Help for Get-EventlLog to see what, if any, filtering options are available.
First of all though, I like to run a quick check on a cmdlet to see what parameters are potentially available. Rather than start reading through the Help, I use Shay Levy’s Get-Parameter function, which you can get from his blog, Get-Parameter - Learn more about your cmdlets.
For Get-EventLog, it produces the following results:
Get-Parameter Get-EventLog
From this information, we can quickly see that there are some possibilities for filtering at the beginning of the pipeline to match the requirements of the event, that is, -InstanceId and -Source.
If you want to find out more about these parameters you can use
Get-Help Get-EventLog –Detailed
or
Get-Help Get-EventLog –Parameter InstanceID
So our initial query of the event log makes use of the following parameters, and we don’t need to pipe the results into Where-Object to carry out the filtering.
Get-EventLog -LogName Application -InstanceId 10001 -EntryType Information -Source Winsrv -Message "The following application attempted to veto the shutdown*"
So it looks like the properties we need to work with for this event are Time and Message.
Get-EventLog -LogName Application -InstanceId 10001 -EntryType Information -Source Winsrv -Message "The following application attempted to veto the shutdown*” | Select Time,Message
However, Time is empty. Puzzling? Something I always remind students in my Windows PowerShell workshops is, “What you see is not necessarily what you get.” That is, the cmdlet designer has chosen to present the output of their cmdlet to the console in a certain way, and that may not necessarily match up with the object that has been returned by the cmdlet.
So, we should pipe our Get-EventLog query into the Get-Member cmdlet to have a closer look.
Get-EventLog -LogName Application -InstanceId 10001 -EntryType Information -Source Winsrv -Message "The following application attempted to veto the shutdown*” | Get-Member
We can see that we actually need to work with the TimeGenerated property—one called Time does not exist.
With the Message property, we don’t need the whole message, just the part that contains the application that is vetoing the shutdown. For that, we can create a calculated property, that is, a custom property of our own. You can see how we do that in the following code. In the expression, we expand the Message property, split it at the ‘:’ character, and use the second element in the array. (Arrays start at 0, so we need to use [1].)
Get-EventLog -LogName Application -InstanceId 10001 -EntryType Information -Source Winsrv -Message "The following application attempted to veto the shutdown*" | select TimeGenerated,@{n='Application';e={(($_ | Select -ExpandProperty Message) -split ':')[1]}}
This gives us the solution to the event as shown here.
While checking out this event, I needed to generate some events in the Application log to match those of the requirements. To do so, I used the Write-EventLog cmdlet to create some (fake) matching entries.
Write-EventLog -LogName Application -Source Winsrv -Category 0 -EventId 10001 -Message "The following application attempted to veto the shutdown: BTTray.exe."
However, when I first ran this on my Windows 7 system, I received the following result.
To have an event in the log of Source Winsrv, it first needs to be registered, and this does not appear to be so by default. You can use the following .NET code to determine if this is the case for any event source.
[system.diagnostics.eventlog]::sourceexists("Winsrv")
And use this code to create one for the Application log:
[system.diagnostics.eventlog]::CreateEventSource("Winsrv",'Application')
Now I can create my required event log entry.
~Jonathan
The 2012 Scripting Games Guest Commentator Week Part 2 will continue tomorrow when we will present the scenario for Event 10.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy