Richard's profileRichard Siddaway's BlogPhotosBlogLists Tools Help

Blog


    November 07

    PowerShell WMI events

    In my previous post ( http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!2598.entry  or http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!2598.entry ) I started to look at WMI events in PowerShell v2.  The win32_process class was used but all that showed us was that a process had started. We need a bit more information.  A bit of digging brought up the Win32_ProcessStartTrace class that seems to do what we want. 

    Register-WMIEvent allows us to specify the class we want to use rather than a query – however if we try that we don’t get anything returned  - oops.

    Looking through the help for Register-WMIEvent shows that we have the possibility of performing an action when the event occurs.  The action scriptblock can use a number of variables including $Event, $EventSubscriber, $Sender, $SourceEventArgs, and $SourceArgs automatic variables.  Wanting to understand these variables I tried dumping it though get-member. 

    PS> Register-WmiEvent -Query "Select * FROM Win32_ProcessStartTrace" -Action {$Event | gm}

    Id              Name            State      HasMoreData     Location             Command
    --              ----            -----      -----------     --------             -------
    2               c1016218-f80... NotStarted False                                $Event | gm

    The subscription runs as a PowerShell job. Using the opening of Notepad to trigger the event we can see that data is returned.

    PS> Get-Job

    Id              Name            State      HasMoreData     Location             Command
    --              ----            -----      -----------     --------             -------
    2               c1016218-f80... Running    True                                 $Event | gm

    And see that we have a few properties to play with.  ComputerName may come in useful if we are dealing with remote machines.

    PS> Receive-Job -Id 2

       TypeName: System.Management.Automation.PSEventArgs

    Name             MemberType Definition
    ----             ---------- ----------
    Equals           Method     bool Equals(System.Object obj)
    GetHashCode      Method     int GetHashCode()
    GetType          Method     type GetType()
    ToString         Method     string ToString()
    ComputerName     Property   System.String ComputerName {get;}
    EventIdentifier  Property   System.Int32 EventIdentifier {get;}
    MessageData      Property   System.Management.Automation.PSObject MessageData {get;}
    RunspaceId       Property   System.Guid RunspaceId {get;}
    Sender           Property   System.Object Sender {get;}
    SourceArgs       Property   System.Object[] SourceArgs {get;}
    SourceEventArgs  Property   System.EventArgs SourceEventArgs {get;}
    SourceIdentifier Property   System.String SourceIdentifier {get;}
    TimeGenerated    Property   System.DateTime TimeGenerated {get;}

    The properties look similar to those we saw in the last post.  Lets dig into SourceEventArgs

    PS> Register-WmiEvent -Query "Select * FROM Win32_ProcessStartTrace" -Action {$Event.SourceEventArgs | gm}

    Id              Name            State      HasMoreData     Location             Command
    --              ----            -----      -----------     --------             -------
    3               8d4246a5-5f8... NotStarted False                                $Event.SourceEventArgs...

    PS> Get-Job

    Id              Name            State      HasMoreData     Location             Command
    --              ----            -----      -----------     --------             -------
    3               8d4246a5-5f8... Running    True                                 $Event.SourceEventArgs...

    PS> Receive-Job -Id 3

       TypeName: System.Management.EventArrivedEventArgs

    Name        MemberType Definition
    ----        ---------- ----------
    Equals      Method     bool Equals(System.Object obj)
    GetHashCode Method     int GetHashCode()
    GetType     Method     type GetType()
    ToString    Method     string ToString()
    Context     Property   System.Object Context {get;}
    NewEvent    Property   System.Management.ManagementBaseObject NewEvent {get;}

     

    Only thing here that look interesting is NewEvent

    PS> Register-WmiEvent -Query "Select * FROM Win32_ProcessStartTrace" -Action {$Event.SourceEventArgs.NewEvent | gm}

    Id              Name            State      HasMoreData     Location             Command
    --              ----            -----      -----------     --------             -------
    4               0857a744-1d3... NotStarted False                                $Event.SourceEventArgs...

    PS> Receive-Job -Id 4

       TypeName: System.Management.ManagementBaseObject#\Win32_ProcessStartTrace

    Name                MemberType Definition
    ----                ---------- ----------
    ParentProcessID     Property   System.UInt32 ParentProcessID {get;set;}
    ProcessID           Property   System.UInt32 ProcessID {get;set;}
    ProcessName         Property   System.String ProcessName {get;set;}
    SECURITY_DESCRIPTOR Property   System.Byte[] SECURITY_DESCRIPTOR {get;set;}
    SessionID           Property   System.UInt32 SessionID {get;set;}
    Sid                 Property   System.Byte[] Sid {get;set;}
    TIME_CREATED        Property   System.UInt64 TIME_CREATED {get;set;}
    __CLASS             Property   System.String __CLASS {get;set;}
    __DERIVATION        Property   System.String[] __DERIVATION {get;set;}
    __DYNASTY           Property   System.String __DYNASTY {get;set;}
    __GENUS             Property   System.Int32 __GENUS {get;set;}
    __NAMESPACE         Property   System.String __NAMESPACE {get;set;}
    __PATH              Property   System.String __PATH {get;set;}
    __PROPERTY_COUNT    Property   System.Int32 __PROPERTY_COUNT {get;set;}
    __RELPATH           Property   System.String __RELPATH {get;set;}
    __SERVER            Property   System.String __SERVER {get;set;}
    __SUPERCLASS        Property   System.String __SUPERCLASS {get;set;}

     

    Now we have got to the information we need.  So how can we use this.  Up to now we have just allowed the job to run and then picked the data from the job.  One option is to write the data to the prompt as shown in this example  http://blogs.msdn.com/powershell/archive/2009/08/30/exploring-wmi-with-powershell-v2.aspx.  A lot of this digging was because I didn’t understand how this was put together.  PowerShell really is the best way to discover how to use PowerShell!!

    This gets us to this script which is modified from the PowerShell Team blog

     

    001
    002
    003
    004
    005
    006
    007
    008
    009
    010
    011
    ## query
    $q = "Select * from Win32_ProcessStartTrace"
    ## action script block
    $a = {
        $eSEANE = $Event.SourceEventArgs.NewEvent
        $str = 'Computer {0},ID {1}, Name "{2}", Time {3}, Source {4}' 
        $data = $str -f $Event.Sender.Scope.Path.Server, $eSEANE.ProcessId, `
          $eSEANE.ProcessName, $Event.TimeGenerated, $Event.SourceIdentifier
        Write-Host $data
    }
    Register-WmiEvent -Query $q -SourceIdentifier "Process Start" -Action $a

     

    Turns out the ComputerName parameter doesn’t work but a comment on the blog shows how Jeffrey Hicks solved the problem.

    What we get now is a listing at our PowerShell prompt  when a new process starts. We can keep working and the data comes through when the prompt is idle.

    Next we will look at closing a process and recording the data in a log

    Technorati Tags: ,,

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    The trackback URL for this entry is:
    http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!2599.trak
    Weblogs that reference this entry
    • None