Weekend Scripter: Playing with PowerShell Processes and Events

Doctor Scripto

Dr 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 

Doctor Scripto
Dr Scripto

Scripter, PowerShell, vbScript, BAT, CMD

Follow Dr Scripto   

0 comments

    Leave a comment