Version 9 of Handling WMI events using TWAPI

Updated 2011-05-06 13:09:38 by Maiki

Small update for twapi 3.0 proc start_process_tracker {} {

        # Get local WMI root provider
        set ::wmi [twapi::_wmi]

        # Create an WMI event sink
        set ::event_sink [twapi::comobj wbemscripting.swbemsink]

        # Attach our handler to it
        set ::event_sink_id [$::event_sink -bind process_start_handler]

        # Associate the sink with a query that polls every 1 sec for process
        # starts.
        $::wmi ExecNotificationQueryAsync [$::event_sink -interface] "select * from __InstanceCreationEvent within 1 where TargetInstance ISA 'Win32_Process'"

} proc process_start_handler {wmi_event args} {

        if {$wmi_event eq "OnObjectReady"} {
                # First arg is a IDispatch interface of the event object
                # Create a TWAPI COM object out of it
                set event_obj [twapi::comobj_idispatch [lindex $args 0]]

                # Get and print the Name property
                puts "Process [$event_obj -with TargetInstance Name] started"

                # Get rid of the event object
                $event_obj -destroy
        }

}

Some examples of handling WMI events through TWAPI COM support. See TWAPI and WMI for examples related to retrieving WMI data.

WMI can be configured to monitor system events and send notifications to an event sink when the events occur. Note that asynchronous notifications in WMI have security issues depending on what you do with the data. Refer to the WMI documentation at [L1 ] for details and steps to secure the notifications.

The examples below illustrate how to set up the event sink and associated handlers using TWAPI COM support. All examples assume you have initialized with

  package require twapi 1.0 ;# Note you need the 1.0 release
  set wmi [twapi::_wmi]

and remember to do a

  $wmi -destroy

at the end.

Also, the Tcl event loop must be running, either through Tk or through a vwait command.


Print a notification when a new process is created

   # Handler invoked when a process is started.  Will print exe name of process.
   proc process_start_handler {wmi_event args} {
       if {$wmi_event eq "OnObjectReady"} {
           # First arg is a IDispatch interface of the event object
           # Create a TWAPI COM object out of it
           set event_obj [twapi::comobj_idispatch [lindex $args 0] true]

           # Get and print the Name property
           puts "Process [$event_obj -with TargetInstance Name] started"

           # Get rid of the event object
           $event_obj -destroy
       }
   }

   # Call to begin tracking of processes.
   proc start_process_tracker {} {
       # Get local WMI root provider
       set ::wmi [twapi::_wmi]

       # Create an WMI event sink
       set ::event_sink [twapi::comobj wbemscripting.swbemsink]

       # Attach our handler to it
       set ::event_sink_id [$::event_sink -bind process_start_handler]

       # Associate the sink with a query that polls every 1 sec for process
       # starts.
       $::wmi ExecNotificationQueryAsync [$::event_sink -interface] "select * from __InstanceCreationEvent within 1 where TargetInstance ISA 'Win32_Process'"
   }

   # Stop tracking of process starts
   proc stop_process_tracker {} {
       # Cancel event notifications
       $::event_sink Cancel

       # Unbind our callback
       $::event_sink -unbind $::event_sink_id

       # Get rid of all objects
       $::event_sink -destroy
       $::wmi -destroy
   }

Category Windows | Category System Administration


Maiki - 2011-05-06 09:08:40

<Small update for twapi 3.0> proc start_process_tracker {} {

        # Get local WMI root provider
        set ::wmi [twapi::_wmi]

        # Create an WMI event sink
        set ::event_sink [twapi::comobj wbemscripting.swbemsink]

        # Attach our handler to it
        set ::event_sink_id [$::event_sink -bind process_start_handler]

        # Associate the sink with a query that polls every 1 sec for process
        # starts.
        $::wmi ExecNotificationQueryAsync [$::event_sink -interface] "select * from __InstanceCreationEvent within 1 where TargetInstance ISA 'Win32_Process'"

} proc process_start_handler {wmi_event args} {

        if {$wmi_event eq "OnObjectReady"} {
                # First arg is a IDispatch interface of the event object
                # Create a TWAPI COM object out of it
                set event_obj [twapi::comobj_idispatch [lindex $args 0]]

                # Get and print the Name property
                puts "Process [$event_obj -with TargetInstance Name] started"

                # Get rid of the event object
                $event_obj -destroy
        }

}