Add to Technorati Favorites
Welcome to ThePowerShellGuy.com Sign in | Join | Help

PowerShell Eventing Library : PSEventing 0.5 Beta released

 

PSEventing 0.5 Beta released !!

PSeventing is a very powerful PowerShell Snapin providing a library for handling events in PowerShell, a must have extension to PowerShell !!

 

Eventhanding suport is a bit limited for version 1.0 of PowerShell, there are some threading problems with for example the .NET filewatcher see : /\/\o\/\/ PowerShelled: MSH directory watcher with popup-balloon ,  I used IronPython as a workaround  :Using IronPython from PowerShell Part 1 : Watch folder for changes without blocking Console .

I  also implemented a non blocking version of the Popup-Balloon script in IronPython, it was still on my "To-Blog-List", not needed anymore so I might skip the blogentry but for the Iron Python Fan's I will still post the script to my blog tomorrow

Also for working with WMI events  we have problems with blocking the console and not be able to Cancel the Event watcher when started, as Ctrl-C does not work, see also  MSH Cluster Watcher script without getting an event we can not stop the Watcher without closing the complete console (Ctrl-Break).

As this is a very big handicap when working with events, and especialy WMI events I use a lot , so this is/was very high on my WishList, and something that I did realy miss in PowerShell (Hence all the workarounds), and belief me I did a lot of begging for better Event support, on Connect the NewGroup and for example on last MVP summit it was my main request to the team ;-)

I talked about the problem with handling events to Oisin ( also developer of the  PowerShell SharePoint Provider and contributor to the PowerShell Community Extensions Project ) on IRC (in the #PowerShell channel on FreeNode) he also agreed on the problem, saw the possibilities and he started to make a Cmdlet for it.

I use this first version for a while now and it is Great !!!, as there where some small issues, that will say small issues in usage, but very hard to solve as they involved threading and Ctrl-C handling (a weak point of PowerShell V1.0 in global, also high on my Wish-List for V2 )  ,Oisin didn't want to release the Snapin , also he made it into a complete library and added help, so what did look like a fast solution resulted in a big project that took a lot of time.

But the Result is really amazing

Oisin has made this into this very cool PowerShell eventing library, and released it on CodePlex :

 

 

as Oisin did the FileWatcher example on the Homepage of the Project I will show how great this solution can be used for WMI Queries also.

for more information about the WMI EventWatcher and how to make it a script on PowerShell, see these posts on my former blog about this topic.

/\/\o\/\/ PowerShelled: Watching FSRM Quota and filescreen events ...

/\/\o\/\/ PowerShelled: MSH Cluster Watcher script (completer script and more info)

I start with making the WMI query, in this case I will watch all processes that do exit : 

PoSH> Add-PSSnapin psEventing                                                                                           
PoSH>                                                                                                                   
PoSH> $query = New-Object System.Management.WQLEventQuery                                                               
PoSH> $query.EventClassName = "__InstanceDeletionEvent"                                                                 
PoSH> $query.WithinInterval = New-TimeSpan -seconds 1                                                                   
PoSH> $query.Condition = "TargetInstance ISA 'Win32_Process'"                                                           
PoSH> $query                                                                                                            
                                                                                                                        
                                                                                                                        
QueryLanguage       : WQL                                                                                               
QueryString         : select * from __InstanceDeletionEvent within 1 where TargetInstance ISA 'Win32_Process'           
EventClassName      : __InstanceDeletionEvent                                                                           
Condition           : TargetInstance ISA 'Win32_Process'                                                                
WithinInterval      : 00:00:01                                                                                          
GroupWithinInterval : 00:00:00                                                                                          
GroupByPropertyList : {}                                                                                                
HavingCondition     :                                                                                                   
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH>                                                                                                                   
PoSH> $watcher = New-Object System.Management.ManagementEventWatcher($query)                                            
PoSH>  

After I made the watcher this way I can now use the tools in the PowerShell Eventing Library, to interact with the eventwatcher,

If you use PowerTab

you can type %[tab]ev to see and easy select from the 4 Cmdlets added by the PsEvents SnapIn,

 (There are 2 more Cmdlets provided to manage the Crtl-C key handling of PowerShell

Start-KeyHandler

Stop-KeyHandler

, very cool stuff also but to much to cover in this blogentry, it us most usefull with the -wait parameter that we also not use here. )   

also you can see in the next example using PowerTab on the parameters of Get_eventBinding that the Get-Eventbinding also has a -IncludeUnboundEvents parameter that is very handy to check the event available on an Object :  

                                                                                                                 
PoSH> %ev                                                                                                               
PoSH>    ev                                                                                                             
PoSH>    Connect-EventListener                                                                                          
PoSH>    Disconnect-EventListener                                                                                       
PoSH>    Get-Event                                                                                                      
PoSH>    Get-EventBinding                                                                                               
PoSH>    Get-EventLog                                                                                                   
PoSH>     [ 1 of 5 ]                                                                                                    
PoSH>                                                                                                                   
PoSH> Get-EventBinding -                                                                                                
PoSH>                     -                                                                                             
PoSH>                     -Debug                                                                                        
PoSH>                     -ErrorAction                                                                                  
PoSH>                     -ErrorVariable                                                                                
PoSH>                     -IncludeUnboundEvents                                                                         
PoSH>                     -OutBuffer                                                                                    
PoSH>                     -OutVariable                                                                                  
PoSH>                     -Variable                                                                                     
PoSH>                     -VariableName                                                                                 
PoSH>                     -Verbose                                                                                      
PoSH>                      [ 4 of 9 ]                                                                                   
PoSH>                                                                                                                   
PoSH> Get-EventBinding watcher -IncludeUnboundEvents                                                                    
                                                                                                                        
VariableName                  EventName                     TypeName                                          Listening 
------------                  ---------                     --------                                          --------- 
watcher                       Disposed                      ManagementEventWatcher                                False 
watcher                       EventArrived                  ManagementEventWatcher                                False 
watcher                       Stopped                       ManagementEventWatcher                                False 
                                                                                                                        
                                                                                                                        
PoSH>                                                                                                                   
PoSH> Connect-EventListener watcher EventArrived -Verbose                                                               
VERBOSE: Target is a ManagementEventWatcher                                                                             
VERBOSE: Now listening for 'EventArrived' events from $watcher                                                          
PoSH>                                                                                                                   
PoSH> $watcher.Start()                                                                                                  
PoSH> calc                                                                                                              
PoSH> sleep 2                                                                                                           
PoSH> gps calc | stop-process                                                                                           
PoSH> $e = get-Event                                                                                                    
                                                                         
PoSH>                                                                              

Now we have used Connect-EventListener to bind to the events of the Watcher object we made, and from now on we can use get-Event at anytime to check if there are events riased by the $watcher WMI event watcher object.

                                                                                                
PoSH> $e                                                                                                                
PoSH>                                                                                                                   
PoSH> $e.Args                                                                                                           
PoSH> $e.Args.NewEvent                                                                                                  
PoSH> $e.Args.NewEvent.TargetInstance | fl Name,ExecutablePath                                                          
PoSH>                                                                                                                   
PoSH> calc                                                                                                              
PoSH> sleep 2                                                                                                           
PoSH> gps calc | stop-process                                                                                           
PoSH>                                                                                                                   
PoSH> get-Event | select @{n='date';e={[datetime]::FromFileTime($_.Args.NewEvent.TIME_CREATED)}},@{n='Server';e={$_.Args
.NewEvent.TargetInstance.__SERVER}},@{n='Process';e={$_.Args.NewEvent.TargetInstance.Description}},@{n='Started';e={([wm
i]'').ConvertToDateTime($_.Args.NewEvent.TargetInstance.CreationDate)}} | select *,@{n='Active';e={$_.Date - $_.Started}
} | ft                                                                                                                  
                                                                                                                        
date                    Server                  Process                 Started                 Active                  
----                    ------                  -------                 -------                 ------                  
5/9/2007 10:51:48 PM    PoshVista1              calc.exe                5/9/2007 10:51:45 PM    00:00:02.5037460        
5/9/2007 10:51:50 PM    PoshVista1              calc.exe                5/9/2007 10:51:47 PM    00:00:02.4226970        
                                                                                                                        
                                                                                                                        
PoSH> $e                                                                                                                
PoSH> calc                                                                                                              
PoSH> sleep 2                                                                                                           
PoSH> gps calc | stop-process                                                                                           
PoSH> $e = get-Event                                                                                                    
PoSH> $e                                                                                                                
PoSH> $e = get-Event                                                                                                    
PoSH> $e                                                                                                                
                                                                                                                        
Occurred                      Source                        Name                          Args                          
--------                      ------                        ----                          ----                          
5/9/2007 10:56:51 PM          variable:watcher              EventArrived                  System.Management.EventArr... 
                                                                                                                        
                                                                                                                        
PoSH> calc                                                                                                              
PoSH> sleep 2                                                                                                           
PoSH> gps calc | stop-process                                                                                           
PoSH> sleep 2                                                                                                           
PoSH> $e = get-Event                                                                                                    
PoSH> $e                                                                                                                
                                                                                                                        
Occurred                      Source                        Name                          Args                          
--------                      ------                        ----                          ----                          
5/9/2007 10:59:16 PM          variable:watcher              EventArrived                  System.Management.EventArr... 
                                                                                                                        
                                                                                                                        
PoSH> $e.Args                                                                                                           
                                                                                                                        
NewEvent                                                    Context                                                     
--------                                                    -------                                                     
System.Management.ManagementBaseObject                      {}                                                          
                                                                                                                        
                                                                                                                        
PoSH> $e.Args.NewEvent                                                                                                  
                                                                                                                        
                                                                                                                        
__GENUS             : 2                                                                                                 
__CLASS             : __InstanceDeletionEvent                                                                           
__SUPERCLASS        : __InstanceOperationEvent                                                                          
__DYNASTY           : __SystemClass                                                                                     
__RELPATH           :                                                                                                   
__PROPERTY_COUNT    : 3                                                                                                 
__DERIVATION        : {__InstanceOperationEvent, __Event, __IndicationRelated, __SystemClass}                           
__SERVER            : PoshVista1                                                                                        
__NAMESPACE         : //./root/CIMV2                                                                                    
__PATH              :                                                                                                   
SECURITY_DESCRIPTOR :                                                                                                   
TargetInstance      : System.Management.ManagementBaseObject                                                            
TIME_CREATED        : 128232179565717710                                                                                
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH> $e.Args.NewEvent.TargetInstance | fl Name,ExecutablePath                                                          
                                                                                                                        
                                                                                                                        
Name           : calc.exe                                                                                               
ExecutablePath : C:\WINDOWS\system32\calc.exe                                                                           
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH> $e.Args.NewEvent.TargetInstance | fl                                                                              
                                                                                                                        
                                                                                                                        
__GENUS                    : 2                                                                                          
__CLASS                    : Win32_Process                                                                              
__SUPERCLASS               : CIM_Process                                                                                
__DYNASTY                  : CIM_ManagedSystemElement                                                                   
__RELPATH                  : Win32_Process.Handle="10084"                                                               
__PROPERTY_COUNT           : 45                                                                                         
__DERIVATION               : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemElement}                                
__SERVER                   : PoshVista1                                                                                
__NAMESPACE                : root\CIMV2                                                                                 
__PATH                     : \\NL-37YHW1J\root\CIMV2:Win32_Process.Handle="10084"                                       
Caption                    : calc.exe                                                                                   
CommandLine                : "C:\WINDOWS\system32\calc.exe"                                                             
CreationClassName          : Win32_Process                                                                              
CreationDate               : 20070509225913.276083+120                                                                  
CSCreationClassName        : Win32_ComputerSystem                                                                       
CSName                     : PoshVista1                                                                                 
Description                : calc.exe                                                                                   
ExecutablePath             : C:\WINDOWS\system32\calc.exe                                                               
ExecutionState             :                                                                                            
Handle                     : 10084                                                                                      
HandleCount                : 49                                                                                         
InstallDate                :                                                                                            
KernelModeTime             : 1093750                                                                                    
MaximumWorkingSetSize      : 1413120                                                                                    
MinimumWorkingSetSize      : 204800                                                                                     
Name                       : calc.exe                                                                                   
OSCreationClassName        : Win32_OperatingSystem                                                                      
OSName                     : Microsoft® Windows Vista™ Ultimate |C:\Windows|\Device\Harddisk0\Partition2                
OtherOperationCount        : 173                                                                                        
OtherTransferCount         : 2632                                                                                       
PageFaults                 : 1203                                                                                       
PageFileUsage              : 1306624                                                                                    
ParentProcessId            : 10408                                                                                      
PeakPageFileUsage          : 1323008                                                                                    
PeakVirtualSize            : 54902784                                                                                   
PeakWorkingSetSize         : 4853760                                                                                    
Priority                   : 8                                                                                          
PrivatePageCount           : 1306624                                                                                    
ProcessId                  : 10084                                                                                      
QuotaNonPagedPoolUsage     : 2400                                                                                       
QuotaPagedPoolUsage        : 114352                                                                                     
QuotaPeakNonPagedPoolUsage : 2688                                                                                       
QuotaPeakPagedPoolUsage    : 114888                                                                                     
ReadOperationCount         : 1                                                                                          
ReadTransferCount          : 12748                                                                                      
SessionId                  : 1                                                                                          
Status                     :                                                                                            
TerminationDate            :                                                                                            
ThreadCount                : 1                                                                                          
UserModeTime               : 156250                                                                                     
VirtualSize                : 54886400                                                                                   
WindowsVersion             : 6.0.6000                                                                                   
WorkingSetSize             : 4837376                                                                                    
WriteOperationCount        : 0                                                                                          
WriteTransferCount         : 0                                                                                          
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH> $e.Args.NewEvent.TargetInstance | fl [a-z]*                                                                       
                                                                                                                        
                                                                                                                        
Caption                    : calc.exe                                                                                   
CommandLine                : "C:\WINDOWS\system32\calc.exe"                                                             
CreationClassName          : Win32_Process                                                                              
CreationDate               : 20070509225913.276083+120                                                                  
CSCreationClassName        : Win32_ComputerSystem                                                                       
CSName                     : PoshVista1                                                                                
Description                : calc.exe                                                                                   
ExecutablePath             : C:\WINDOWS\system32\calc.exe                                                               
ExecutionState             :                                                                                            
Handle                     : 10084                                                                                      
HandleCount                : 49                                                                                         
InstallDate                :                                                                                            
KernelModeTime             : 1093750                                                                                    
MaximumWorkingSetSize      : 1413120                                                                                    
MinimumWorkingSetSize      : 204800                                                                                     
Name                       : calc.exe                                                                                   
OSCreationClassName        : Win32_OperatingSystem                                                                      
OSName                     : Microsoft® Windows Vista™ Ultimate |C:\Windows|\Device\Harddisk0\Partition2                
OtherOperationCount        : 173                                                                                        
OtherTransferCount         : 2632                                                                                       
PageFaults                 : 1203                                                                                       
PageFileUsage              : 1306624                                                                                    
ParentProcessId            : 10408                                                                                      
PeakPageFileUsage          : 1323008                                                                                    
PeakVirtualSize            : 54902784                                                                                   
PeakWorkingSetSize         : 4853760                                                                                    
Priority                   : 8                                                                                          
PrivatePageCount           : 1306624                                                                                    
ProcessId                  : 10084                                                                                      
QuotaNonPagedPoolUsage     : 2400                                                                                       
QuotaPagedPoolUsage        : 114352                                                                                     
QuotaPeakNonPagedPoolUsage : 2688                                                                                       
QuotaPeakPagedPoolUsage    : 114888                                                                                     
ReadOperationCount         : 1                                                                                          
ReadTransferCount          : 12748                                                                                      
SessionId                  : 1                                                                                          
Status                     :                                                                                            
TerminationDate            :                                                                                            
ThreadCount                : 1                                                                                          
UserModeTime               : 156250                                                                                     
VirtualSize                : 54886400                                                                                   
WindowsVersion             : 6.0.6000                                                                                   
WorkingSetSize             : 4837376                                                                                    
WriteOperationCount        : 0                                                                                          
WriteTransferCount         : 0                                                                                          
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH> $e.Args.NewEvent.TargetInstance | fl ProcessId,Name,ExecutablePath                                                
                                                                                                                        
                                                                                                                        
ProcessId      : 10084                                                                                                  
Name           : calc.exe                                                                                               
ExecutablePath : C:\WINDOWS\system32\calc.exe                                                                           
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH>                                                                                

 You can see that we have some event information but we get also back the Process information so we can use that also,

Next a will show a oneliner I made for the first version, that creates and formats a nice list ofthe processes with information about when they stopped when the ended and how long they did run.

get-Event | select @{n='date';e={[datetime]::FromFileTime($_.Args.NewEvent.TIME_CREATED)}},@{n='Server';e={$_.Args.NewEvent.TargetInstance.__SERVER}},@{n='Process';e={$_.Args.NewEvent.TargetInstance.Description}},@{n='Started';e={([wmi]'').ConvertToDateTime($_.Args.NewEvent.TargetInstance.CreationDate)}} | select *,@{n='Active';e={$_.Date - $_.Started}} | ft

 

[PoSH]> calc                                                                                                            
[PoSH]> mspaint                                                                                                         
[PoSH]> sleep 2                                                                                                         
[PoSH]> gps calc | stop-process                                                                                         
[PoSH]> gps mspaint | stop-process                                                                                      
[PoSH]> sleep 1                                                                                                         
[PoSH]>                                                                                                                 
[PoSH]> get-Event | select @{n='date';e={[datetime]::FromFileTime($_.Args.NewEvent.TIME_CREATED)}},@{n='Server';e={$_.Ar
gs.NewEvent.TargetInstance.__SERVER}},@{n='Process';e={$_.Args.NewEvent.TargetInstance.Description}},@{n='Started';e={([
wmi]'').ConvertToDateTime($_.Args.NewEvent.TargetInstance.CreationDate)}} | select *,@{n='Active';e={$_.Date - $_.Starte
d}} | ft                                                                                                                
                                                                                                                        
date                    Server                  Process                 Started                 Active                  
----                    ------                  -------                 -------                 ------                  
5/10/2007 1:20:46 AM    PoshVista1              SearchProtocolHost.exe  5/10/2007 1:19:37 AM    00:01:08.5937505        
5/10/2007 1:20:46 AM    PoshVista1              SearchFilterHost.exe    5/10/2007 1:19:38 AM    00:01:08.3593755        
5/10/2007 1:22:00 AM    PoshVista1              calc.exe                5/10/2007 1:21:57 AM    00:00:02.4062505        
5/10/2007 1:22:01 AM    PoshVista1              mspaint.exe             5/10/2007 1:21:58 AM    00:00:03.2968755        
                                                                                                                        
                                                                                                                        
[PoSH]>                                                                          

*Note* When Oisin did see this one-liner he added also the Occurred property to the returned object so the WMI date translation is not needed anymore, but I did leave it in just to Show Off ;-)

You can see how powerfull and handy this is you define the events you want to watch, and can check them at any time you want (Tip leave this WMI eventwatcher for processess running for a couple of hours and then check the events like this you will be amazed ;-)

This Snapin really does add a lot of extra value and possibilities to the eventhandling of PowerShell I allready can not live without it anymore thats for sure , and it is another example what a great work is done within the PowerShell community

Thanks again to Oisin for fullfilling one of the most important PoSH feature wishes for me, and for makeing PsEvents available to the PowerShell community.

enjoy,

Greetings /\/\o\/\/ 

Published Wednesday, May 09, 2007 6:35 PM by admin

Comments

# Powershell Eventing 0.5 beta released at codeplex

Oisin has created a well designed solution to a major flaw in powershell - lack of event handling. Powershell

Thursday, May 10, 2007 1:01 AM by Powershell News

# PowerShell eventing library 1.0 Released

Oisin, did release version 1.0 of his very cool PowerShell eventing library (See also my former entry

Monday, July 16, 2007 5:04 AM by The PowerShell Guy
Anonymous comments are disabled