Getting notified by a Windows Service status change in C# .NET
August 22, 2017 Leave a comment
The ManagementEventWatcher object in the System.Management namespace makes it possible to subscribe to events within the WMI – Windows Management Instrumentation – context. A change in the status of a Windows service is such an event and it’s possible to get notified when that happens.
We saw examples of WMI queries on this blog before – check the link below – and the ManagementEventWatcher object also requires an SQL-like query string. Consider the following function:
private static void RunManagementEventWatcherForWindowsServices() { EventQuery eventQuery = new EventQuery(); eventQuery.QueryString = "SELECT * FROM __InstanceModificationEvent within 2 WHERE targetinstance isa 'Win32_Service'"; ManagementEventWatcher demoWatcher = new ManagementEventWatcher(eventQuery); demoWatcher.Options.Timeout = new TimeSpan(1, 0, 0); Console.WriteLine("Perform the appropriate change in a Windows service according to your query"); ManagementBaseObject nextEvent = demoWatcher.WaitForNextEvent(); ManagementBaseObject targetInstance = ((ManagementBaseObject)nextEvent["targetinstance"]); PropertyDataCollection props = targetInstance.Properties; foreach (PropertyData prop in props) { Console.WriteLine("Property name: {0}, property value: {1}", prop.Name, prop.Value); } demoWatcher.Stop(); }
We declare the query within an EventQuery object. Windows services are of type “Win32_Service” hence the “where targetinstance isa ‘Win32_Service'” clause. “within 2” means that we want to be notified 2 seconds after the status change has been detected. A change event is represented by the __InstanceModificationEvent class. There are many similar WMI system classes. A creation event corresponds to the __InstanceCreationEvent class. So the query is simply saying that we want to know of any status change in any Windows service 2 seconds after the change.
The timeout option means that the ManagementEventWatcher object will wait for the specified amount of time for the event to occur. After this a timeout exception will be thrown so you’ll need to handle that.
In order to read the properties of the Windows service we need to go a level down to “targetinstance” and read the properties of that ManagementBaseObject. Otherwise the “nextEvent” object properties are not too informative.
Run this code, open the Windows services window and stop or pause any Windows service. I stopped the Tomcat7 service running on my PC and got the following Console output:
You can of course refine your query using the property names of the target instance. You can always check the property names on MSDN. E.g. if you open the above link to the Win32_Service object then you’ll see that it has a “state” and a “name” property. So in case you’ll want to know that a service name “Tomcat7” was stopped then you can have the following query:
eventQuery.QueryString = "SELECT * FROM __InstanceModificationEvent within 2 WHERE targetinstance isa 'Win32_Service' and targetinstance.state = 'Stopped' and targetinstance.name = 'Tomcat7'";
In this case starting Tomcat7 won’t trigger the watcher. Neither will stopping any other Windows service. The event watcher will only react if a service names “Tomcat7” was stopped, i.e. the “Status” property of the target instance was set to “Stopped”.
You can view all posts related to Diagnostics here.