Weekend Scripter: Playing with PowerShell Processes and Events

Doctor Scripto

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 Exited event 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:

Image of command output

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 

0 comments

Discussion is closed.

Feedback usabilla icon