Visual Basic WMI System Services
Win32_Process: WMI Enables Process Monitoring
     
Posted:   Monday April 25, 2005
Updated:   Monday November 28, 2011
     
Applies to:   VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   Windows NT, 2000, XP. See Prerequisites below.
Author:   VBnet - Randy Birch, Larry Serflaten
     

Related:  

 
     
 Prerequisites
Windows Script Host is built into Microsoft Windows 98, 2000, ME and XP. If you are running Windows 95 or NT4, you can download Windows Script Host from the Microsoft Windows Script Technologies Web site at http://msdn.microsoft.com/scripting/. Some information is not returned on non-NT-based systems.

A reference set in Projects / References to the Microsoft WMI Scripting Library.


Larry posted a message to a newsgroup in response to a request for code to monitor when a particular executable was started on the local machine.  I've utilized his basic code to provide monitoring capability for both the local machine or for any other machine on the network. I also replaced a Do Loop/DoEvents with a Timer routine.

Although I'm not fond of scripting, WMI is a powerful set of well thought out classes and methods. The ability to utilize SQL-like queries against the classes makes demos like this possible.

There are five illustrations cycling to the right. The first is the startup state of the demo. The second shows WMI monitoring for the creating of new Internet Explorer (iexplore.exe) instances on my remote laptop computer. The third demo shows the result of starting three IE sessions; the fourth the result of closing one session, and the last the termination of the monitoring when the started sessions have all been terminated.

If there is one drawback to this demo, and WMI in general, it is that the application becomes unresponsive while waiting for the methods to complete, displaying a "Switch to" and "Retry" dialog if the form is acted upon before the WMI code has completed. This app is no different in this regard, with an additional twist...

The SQL statement invokes the WMI ExecNotificationQuery method to create the process watcher, then starts a timer which handles the following messages. But, when the code calls the objEventSource.NextEvent() method the code execution stops there, and will not continue until a notification is received.  What this means practically is that once this demo has started, you must start and close at least one instance of the process being monitored, otherwise the app will sit at the objEventSource.NextEvent() line and throw the "Switch To" dialog if intervention is attempted.  Because of this I recommend this code be placed in an out-of-process ActiveX exe which can raise events in the calling app without requiring the user to cease using the application.  That aspect I'll leave to you; just remember these limitations when testing this demo.  Also pay attention to the machine name you specify if not the local machine (specified as a period).  WMI does not check for the validity or existence of the specified machine, thus if a typo is made you'll have to kill the demo with task manager since you'll never be able to create and close the single instance required to terminate the demo.

Here's the pseudo-code on what occurs in the demo:

  • BeginProcessMonitor is called specifying the local or remote machine, the exe to monitor, and the timer firing interval.
  • BeginProcessMonitor creates a objSWbemServices object for the specified machine, and executes an ExecNotificationQuery against the object for __InstanceOperationEvent. A timer is then started to poll for event notifications.
  • In the timer event the objEventObject is set to objEventSource.NextEvent(), which is where the code hangs until an event is received. A select case determines if the event was a Creation or Deletion (app closing) event, and increments a static counter showing how many instances have been started.
  • The timer continues to fire while the counter is > 0. When 0 is reached (the number of instances started and tracked by the process monitor equals the number of instances closed), the timer is disabled and the objects are deleted, terminating the monitoring.

It is important to note that, for example, if the user already had started 3 instances of the application prior to starting the monitoring app, and during monitoring 2 new instances were created, the counter would be 2, not 5 as the monitor knows nothing about the initial 3 instances. But as each instance is from the exe being monitoring, any 2 of the 5 instances running can be closed which will terminate the monitoring.  In other words, do not assume that the processes started are the same processed that were terminated, as the monitor can not know anything about previously-started instances.

 BAS Module Code
None.

 Form Code
To a form add a command button (Command1), a text box (Text1), a timer (Timer1) and a label (Lable1). Set a reference in Projects / References to the Microsoft WMI Scripting Library, and add the following to the form:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private objSWbemServices As SWbemServices
Private objEventObject As SWbemObjectEx
Private objEventSource As SWbemEventSource
Private sProcessToMonitor As String
Private sMachineToMonitor As String


Private Sub Form_Load()

   Text1.Text = "iexplore.exe"  'monitor for Internet Explorer
   Command1.Caption = "Monitor for Process"
   Label1.Caption = "Monitoring not active"
   Label1.AutoSize = True
   
End Sub


Private Sub Command1_Click()

   Dim sAppToMonitor As String
   
  'monitor the current machine
   sAppToMonitor = Text1.Text
   Call BeginProcessMonitor("\\.", sAppToMonitor, 100)
   
  '(remote machine syntax:)
  'Call BeginProcessMonitor("\\laptopxp", sAppToMonitor, 100)
   
End Sub


Private Sub BeginProcessMonitor(sComputer As String, _
                                sProcessName As String, _
                                dwMonitorIntervalMs As Long)

   sProcessToMonitor = sProcessName
   sMachineToMonitor = sComputer
   
  'get service
   Set objSWbemServices = GetObject("winmgmts:" & _
                                    "{impersonationLevel=impersonate}!" & _
                                     sComputer & "\root\cimv2")

  'Create a sql statement to monitor for
  'the creation of the passed process (file) name.
  
  'The 'WITHIN' parameter indicates the number of
  'seconds the notification polls for new instances.
  'ISA indicates the type of notification to poll.
  'TargetInstance.Name is the name of the exe to monitor.
   Set objEventSource = objSWbemServices.ExecNotificationQuery( _
      "SELECT * FROM __InstanceOperationEvent " & _
      "WITHIN 1 " & _
      "WHERE TargetInstance " & _
      "ISA 'Win32_Process' " & _
      "AND TargetInstance.Name = '" & sProcessName & "'")
      
  'Engage a timer to provide the polling
  'for the process creation and destruction.
   With Timer1
      .Interval = dwMonitorIntervalMs
      .Enabled = True
   End With
   
   Label1.Caption = "Monitoring for " & sProcessName & " on machine " & sComputer
   
End Sub


Private Sub Timer1_Timer()

   Static processCount As Long
   
  'once the timer fires, code execution stops
  'at the next line. The form becomes inactive,
  'and execution will not continue until the
  'event fires. This means that, with this
  'demo, at least one instance of the
  'desired process must be started on the
  'specified machine before the app can be closed.
   Set objEventObject = objEventSource.NextEvent()

   Select Case objEventObject.Path_.Class
      Case "__InstanceCreationEvent"
         processCount = processCount + 1
         Label1.Caption = "Instance #" & processCount & _
                          " of " & sProcessToMonitor & _
                          " was just started on " & sMachineToMonitor
    
      Case "__InstanceDeletionEvent"
         processCount = processCount - 1
         Label1.Caption = "An instance of " & sProcessToMonitor & _
                          " was just stopped." & _
                          " Processes remaining: " & processCount
          
         'when processcount=0, disable the timer
          If processCount = 0 Then
            Timer1.Enabled = False
            Label1.Caption = "All instances closed. " & _
                             "Monitoring has been disabled."
        
            Set objEventObject = Nothing
            Set objEventSource = Nothing
            Set objSWbemServices = Nothing
        End If
         
    End Select
    
End Sub
 Comments

 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter