Hey, Scripting Guy! I have a Windows Server 2003 computer that I need to monitor for reboots. This may sound rather strange, but this server is more of a workstation, and we have a user mode application that runs under an actual user account. Therefore, we log on using the ID we have set up, launch the application, lock the console of the server, and that is the way the program is supposed to run. Once a day, a user goes to the server, unlocks the console, maximizes the application, and runs a report on the locally attached printer. The user is then supposed to minimize the application, lock the workstation, and collect the report. Unfortunately, if someone new runs the report about half the time, that person will shutdown the server, or log off the user account instead of locking the console. When this happens the application misses data, and it hoses our accounting for the month. Is there a way to use WMI to let me know when someone either logs the user off, or shuts down the server? I know I can use ping to let me know if the server is shutdown, but this does nothing for logoffs.
— SM
Hello SM,
Microsoft Scripting Guy Ed Wilson here. It has been a lovely day in Charlotte, North Carolina, in the United States of America. The sky has been a deep clear blue that occurs after an onslaught of rain cleanses the sky. It reminds me of the sky I saw in Alaska while I was up there teaching a Windows PowerShell workshop. As you can see in the following photo, it is not the color that was the reminder, but maybe the absence of clouds in the sky. We do not have stark mountains or moose in Charlotte, but we do have trees and a few creek beds. So maybe there is not as strong a parallel as I was originally planning. Maybe I just miss Alaska.
SM, you know your current situation is not ideal, and I hope your application is not running as a member of the Domain Admins, although I would not be surprised. The best solution would be to create a custom profile that does not include the logoff or shutdown buttons on the menu. Or better yet, you could remove the shutdown privilege from the user account that is logged onto the machine. However, you know your own business rules and environment much better than I do.
To monitor for shutdown or logoff events, you can use the WMI class Win32_ComputerShutdownEvent. The Win32_ComputerShutdownEvent WMI class first appeared in Windows XP. It is therefore available on your Windows Server 2003 machine. To use this event class, you do not need to write a generic event query. Use the Register-WmiEvent cmdlet, and specify the class name of Win32_ComputerShutdownEvent. Target your remote computer by name or by IP address. If you need to supply alternate credentials for the command to work, you can use the –credentials parameter and you will be prompted for the password. This command is seen here:
Register-WmiEvent -Class win32_computerShutdownEvent -ComputerName win2003
After you have an event subscription, by using the Get-Event cmdlet you can retrieve any events that may have been generated. If you did not specify a source identifier when you used the Register-WmiEvent cmdlet, the Get-Event cmdlet will return all events that have been received. This command is seen here as it returns two events:
PS C:> Get-Event
ComputerName :
RunspaceId : 7bbb485c-6303-4d1e-9084-bc46851990d5
EventIdentifier : 1
Sender : System.Management.ManagementEventWatcher
SourceEventArgs : System.Management.EventArrivedEventArgs
SourceArgs : {System.Management.ManagementEventWatcher, System.Management.EventArrivedEventArgs}
SourceIdentifier : 5ff0a4c6-cb25-45c3-8efc-2c48b722ff34
TimeGenerated : 4/12/2010 2:13:06 PM
MessageData :
ComputerName :
RunspaceId : 7bbb485c-6303-4d1e-9084-bc46851990d5
EventIdentifier : 2
Sender : System.Management.ManagementEventWatcher
SourceEventArgs : System.Management.EventArrivedEventArgs
SourceArgs : {System.Management.ManagementEventWatcher, System.Management.EventArrivedEventArgs}
SourceIdentifier : 5ff0a4c6-cb25-45c3-8efc-2c48b722ff34
TimeGenerated : 4/12/2010 2:13:29 PM
MessageData :
The data we are interested in comes from the NewEvent property. It returns the machine name and the type of event that was generated. A type of 1 is a shutdown or a reboot. A type of 0 means that the event was triggered by a logoff:
PS C:> $a[1].sourceEventArgs.NewEvent
__GENUS : 2
__CLASS : Win32_ComputerShutdownEvent
__SUPERCLASS : Win32_ComputerSystemEvent
__DYNASTY : __SystemClass
__RELPATH :
__PROPERTY_COUNT : 4
__DERIVATION : {Win32_ComputerSystemEvent, __ExtrinsicEvent, __Event, __IndicationRelated…}
__SERVER :
__NAMESPACE :
__PATH :
MachineName : WIN2003
SECURITY_DESCRIPTOR :
TIME_CREATED : 129155696093028224
Type : 1
Because you already know the computer name, all you are interested in is the time the event was generated and the type of event. You can obtain this information by piping the results to the Foreach-Object cmdlet as seen here:
PS C:> Get-Event | Foreach-Object { Write-Host $_.timeGenerated $_.sourceEventArgs.NewEvent.type }
4/12/2010 2:13:06 PM 0
4/12/2010 2:13:29 PM 1
PS C:>
These commands and the associated results are seen in the following image.
SM, that is all there is to using WMI eventing. This also concludes our WMI Week articles. Join us tomorrow when we open our virtual mailbag and examine questions that only require a short answer—that is right, it is time once again for Quick-Hits Friday. We will talk about…wait a minute.
If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments