Trevor Sullivan is a pursuer of all types of knowledge, and is particularly passionate about technology and technical communities. He has been working primarily with Microsoft solutions since 2004. Trevor has received public recognition from Microsoft for his contributions to the Windows PowerShell community, and he has also written several guest blogs for the Hey, Scripting Guy! Blog. One of his more notable achievements is the release of the PowerEvents module for PowerShell, which is available on CodePlex.

For the 2012 Scripting Games Advanced Event 1, we have a script that is supposed to monitor whether Notepad is running. Now, you may or may not agree that Notepad is a mission critical app, and if it is, maybe it should not be—but that is not for us to decide unfortunately. It seems that the fictional know-it-all character in our scenario may need some directional advice on his scripting skills.

After analyzing the sample code, we can see that the “notepad” process is being assigned to a variable called $notepad. If the notepad process does not exist, he would receive an error message from the Get-Process cmdlet along the lines of: “Cannot find a process with the name notepad.” When this is done, the code iterates ten times with the following commands: sleep for one (1) second, and echo the value of the $notepad variable to the Windows PowerShell pipeline.

This code appears to be intended to throw an error if the critical process “notepad” does not exist during any of those ten iterations. However, this is not what will occur. Because the $notepad variable is only being assigned once at the beginning, any value that is contained within it will persist even after the notepad process ceases to exist.

To correct this problem, we need to ensure that we are repeatedly checking for the existence of the notepad process. We can achieve this most simply, by moving the line with the call to Get-Process inside the For looping construct.

for ($i = 1 ; $i -le 10 ; $i++) {

$notepad = Get-Process notepad;

start-sleep 1

$notepad

}

You might notice that this code will still throw an error when the Get-Process cmdlet is called, if the notepad process does not exist. Because this may be unnecessary for achieving the desired results, we can suppress the error message only for the one command. To do this, we use the ErrorAction parameter of the Get-Process cmdlet, and set it to SilentlyContinue. You can alternatively achieve this by setting the built-in $ErrorActionPreference variable to the same value.

for ($i = 1 ; $i -le 10 ; $i++)

{

$notepad = Get-Process notepad -ErrorAction SilentlyContinue;

start-sleep 1

$notepad

}

This concludes our analysis of the 2012 Scripting Games Advanced Event 1. Thanks for participating in the Microsoft Scripting Games for 2012, and best of luck to you!

~Trevor

Guest Commentator Week will continue tomorrow when we will see what the next guest commentators have to say about Event 2 in the 2012 Scripting Games.

I also found this event to be misleading. Trying to figure out what the boss wanted I noticed the script name as MonitorNotepadFor10Seconds.ps1, and noticed that the script montitors notepad once a second for 10 seconds, it does not monitor notepad for a full 10 seconds. So I changed my script to:

$notepad = Get-Process notepad

$timeout = new-timespan -Seconds 10

$stopWatch = [diagnostics.stopwatch]::StartNew()

while ($stopWatch.elapsed -lt $timeout){

$notepad

}

While I clearly missed the refresh or including the Get-Process in the loop, I believe I fixed of the boss's requirements by montoring Notepad for 10 seconds. IMO this would truely monitor Notepad for 10 seconds if I had caught the refresh issue. Too bad this was the first event, I bet it knocked quite a few people out.

My interpretation was that you are monitoring a "particular" process. Thus a single Get-Process, which now holds all the details of the process(s) at the onset of the monitoring. By then, within the loop, checking for the $notepad.Responding property. This would means you are monitoring this process and no others.

If you place the Get-Process inside the loop, then you open the possibility of the process you want to monitor closing (or crashing) and a new one spawning without your knowledge.

Lastly, the question spoke about making as FEW changes as possible to the co-workers code. By moving the Get-Process into the Loop, I believe you are making a major design change, which changes the overall behavior of the script. The Co-worker could have intended to only monitor this one process.

I agree, the question left a lot open to interpretation, perhaps too much.

I got marked down for a solution very similar to the one above too; specifically for including an -erroraction silentlycontinue.

I saw lots of people used a .refresh() inside the loop. But if notepad wasn't running at the outset and started while the code was running, the code would error for all iterations, even though notepad was running for some of them. For me, that justifies moving it inside the loop.