Summary: Microsoft Scripting Guy, Ed Wilson, talks about playing with processes and events in Windows PowerShell.
Microsoft Scripting Guy, Ed Wilson, is here. This morning I woke up and I had an idea. This happens to me sometimes. Not often. But occasionally. And here it was. I could not get it out of my mind...
Can I use an event from a specific process? I wonder. I should be able to do this, but hmmmm. I know a process that I retrieve by using the Get-Process cmdlet is really an instance of System.Diagnostics.Process. I also know that in addition to having methods and properties, it has events. Here are the events I get when I look at a specific process:
PS C:\> Get-Process notepad | Get-Member -MemberType Event
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Disposed Event System.EventHandler Disposed(System.Object, System.Event...
ErrorDataReceived Event System.Diagnostics.DataReceivedEventHandler ErrorDataRec...
Exited Event System.EventHandler Exited(System.Object, System.EventArgs)
OutputDataReceived Event System.Diagnostics.DataReceivedEventHandler OutputDataRe...
Without getting all froggy and looking stuff up in MSDN, I figure that I have a pretty good idea of what an Exitedevent might really be—it is an event that is raised when a particular process exits.
Let me try the Windows PowerShell console
I decided to launch Notepad, and then use the Get-Process cmdlet to retrieve that instance of Notepad. Now I use the Register-ObjectEvent cmdlet, supply the Process object as an InputObject, and I specify that I want to monitor for the Exited event. In the action portion, I start Notepad, and I unregister the event subscriber.
I press ENTER, and I wait.
I close Notepad…
And I wait.
And I wait.
And I wait.
Nothing happens. Bummer.
I press ENTER in the Windows PowerShell console, and suddenly Notepad reappears. Hmmm…I wonder if this is an STA/MTA kind of thing. I launch Windows PowerShell in MTA mode (powershell –mta) and in STA mode (powershell –sta). Still nothing. It only works after I press ENTER. Bummer. Not such a good deal at this point. By the way, here is a screenshot:
One of the nice things about using the Register-ObjectEvent cmdlet is that it does not require me to launch an elevated Windows PowerShell console (or ISE). This is great because I seldom launch Windows PowerShell with elevated permission. Most of the time, I try things without elevation.
What about the ISE?
I open the Windows PowerShell ISE and type my script:
Start-Process notepad
$n = Get-Process notepad
$job = Register-ObjectEvent -InputObject $n -EventName exited -SourceIdentifier notepad -Action {
Start-Process notepad
Get-EventSubscriber | Unregister-Event }
When I run the script, Notepad appears. Cool. I close Notepad, and it immediately reappears. Cool. If I close that instance of Notepad, however, Notepad remains closed. This is due to the fact that I am monitoring a specific instance of Notepad, and once I close that particular instance of Notepad, the new instance is a different process. Therefore, I cannot call the object event from that new process because I have not captured it in the $n variable.
Advantages?
Using Register-ObjectEvent seems to have the following advantages for me:
- Does not automatically require admin rights
- Syntax is easier
- Really fast
- Lower overhead
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy