Hey, Scripting Guy! Question

Hey, Scripting Guy! Is there any way to permanently change the priority of a process? If there isn’t, how can I write a script that will monitor for new instances of this process and then change the priority each time the application runs?

-- AM

SpacerHey, Scripting Guy! AnswerScript Center

Hey, AM. You know, just yesterday we noted that Hey, Scripting Guy! is theplaceto come if you’re looking for the inside scoop on what’s going on in the world of system administration scripting. To prove it, in yesterday’s column we told you about three new challenges that have been added to the 2008 Winter Scripting Games. If that’s not a scoop, well, we’d like to know what is.

Note. According to Merriam-Webster’s online dictionary a scoop is “small spoon-shaped utensil or instrument for cutting or gouging.” So there!

Oh, wait; that’s the wrong definition. Try this one instead: “information especially of immediate interest.” So there!

Of course, we realize that many of you are still a little skeptical. “OK, so you had one scoop,” you’re thinking. “What do you want, a Pulitzer Prize for journalism?”

Well, now that you mention it, yes, we do want a Pulitzer prize for journalism. (Now that we’ve won a TABBIE Award, well, the Pulitzer is about the only award we haven’t won.) That’s why we decided to win you skeptics over by presenting you with yet another scoop: in addition to all the other great prizes being handed out during the upcoming Scripting Games we’re going to be giving away 50 copies of Windows Vista Ultimate!

That’s right, Windows Vista Ultimate, the, well, ultimate operating system. (Don’t believe us? Then count the number of checkmarks on this page. What did we tell you?) Windows Vista Ultimate is pretty darn cool, but it’s also a little pricey; the suggested retail price for a single copy is $958,000. That’s a lot of money for an operating system.

Well, OK, the suggested retail price is actually $399; for many people, however, it might as well be $958,000. But that’s life, right? After all, Windows Vista Ultimate is packed with cool new features like Windows Media Center and BitLocker Drive Encryption, and cool new features like that don’t come free.

Unless you take part in the 2008 Winter Scripting Games (February 15th through March 3rd, right here in the Script Center). Enter a single event in the Scripting Games, and you’ll be eligible to win a free copy of Windows Vista Ultimate. Heck, enter the Games and you will win a free copy of Windows Vista Ultimate!

Just a second …. Um, OK, if you say so.

The Scripting Editor has suggested that we change that statement to the following:

Enter the Games and you might win a free copy of Windows Vista Ultimate.

As you wish, Scripting Editor.

Note. Personally we still think that you will win a copy. But we have to go along with what the Scripting Editor says. After all, she’s big (way bigger than any of us), and she’s mean.

Editor’s Note. Well, she’s bigger (taller, anyway) than the Scripting Guy who writes this column. But then again, who isn’t?

Pretty exciting news, huh? And if that’s not enough here’s another scoop for you: today’s column features a script that can automatically change the priority of any new instances of Notepad that get started on a computer. We couldn’t find a simple, surefire way to permanently change the priority of a process. But this script does the next best thing: it monitors for new instances of Notepad and, any time it finds one, it immediately changes the priority of the process. Notepad will still start with Normal priority, but in a matter of seconds that priority will be changed to Below Normal.

Try to find a scoop like that in The New York Times or The Wall Street Journal!

Well, OK, good point. But try to find a scoop like that in The New York Times.

Here’s the script:

Const BELOW_NORMAL = 16384

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colProcesses = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceCreationEvent Within 5 Where TargetInstance ISA 'Win32_Process'")

Do While True
    Set objLatestProcess = colProcesses.NextEvent
    If objLatestProcess.TargetInstance.Name = "notepad.exe" Then
        objLatestProcess.TargetInstance.SetPriority(BELOW_NORMAL)
    End If
Loop

So how does this script actually work? Well, to begin with, we define a constant named BELOW_NORMAL and set the value to 16384. (Which, by amazing coincidence, just happens to be the exact number of things the Scripting Guy who writes this column still has to finish in order to be ready for the Scripting Games.) This constant enables us to set the priority for our process to Below Normal. Would you prefer to set the priority to something other than Below Normal? Then take a peek at the Microsoft Windows 2000 Scripting Guide for information on the other available priorities and the required constant values.

After defining the constant we connect to the WMI service on the local computer. (And sure, we could use this same script to monitor and change process priorities on a remote computer. All we have to do is assign the name of that computer to the variable strComputer.) Once we’re connected to the WMI service we can then use the following query to create an event subscription that notifies us any time a new process is created:

Set colProcesses = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceCreationEvent Within 3 Where TargetInstance ISA 'Win32_Process'")

We won’t discuss the details of the ExecNotificationQuery method in today’s column; if you’d like to know more about what this query does – and how it does it – you might want to take a look at the Scripting Guys webcast An Ounce of Prevention: An Introduction to WMI Events. For now, suffice to say that every 3 seconds (Within 3) the query checks the __InstanceCreationEvent class (a class that keeps track of new instances of all WMI objects). If any new processes have been created (TargetInstance ISA 'Win32_Process') our script will be notified of that fact. If no new processes have been created everything will pause for 3 seconds; when those 3 seconds are up ExecNotificationQuery will check the __InstanceCreationEvent class again. And again. And again. Ad infinitum.

After creating the event subscription query we set up a Do loop designed to run forever. (Which, by the way, is one good reason to run this script in a command window under CScript; that way you can terminate the script simply by closing the command window.) Inside the loop the first thing we do is execute the following line of code:

Set objLatestProcess = colProcesses.NextEvent

This line causes the script to “block” until it receives a notice telling it that a new process has been created; that simply means that the script is going to pause on this line of code and not budge, at least not until a new process has been created. If and when a new process is created, we check to see if the process Name (or, more correctly, the Name of the TargetInstance, the new member of the __InstanceCreationEvent class) is equal to notepad.exe:

If objLatestProcess.TargetInstance.Name = "notepad.exe" Then

If the Name isn’t equal to notepad.exe then we simply zip back to the top of the loop and wait for the next event to occur. (That is, the next process to be created.) If the Name is equal to notepad.exe then we use this line of code to set the priority for this new instance of Notepad to Below Normal:

objLatestProcess.TargetInstance.SetPriority(BELOW_NORMAL)

And then, once more, it’s back to the top of the loop where we wait for the next process to be created. Each time an instance of Notepad is created the priority will be reset to Below Normal, something we can verify by looking at Task Manager:

Spacer


Cool, huh? When’s the last time you saw a picture like that in The New York Times?

Really? Guess we must not have seen the paper that day.

That should do it, AM; as long as this script is running any new instance of Notepad that starts on the computer will have its priority automatically switched to Below Normal (more commonly-referred to as “Scripting Guys mode”). It’s not the same thing as permanently changing the process priority, but it’s not bad.

Before you all go, don’t forget that the Scripting Games start right here on Friday, February 15th. We’ve got fun, we’ve got prizes, we’ve got scripting competitions; what more could you ask for?

Good point: food would be nice, wouldn’t it? Tell you what, enter the Scripting Games and the Scripting Guys will send pizza and beer to everyone! On the house!

Um, sorry. Apparently that sentence should have read:

Enter the Scripting Games and the Scripting Guys won’t send pizza and beer to everyone!

We apologize for any misunderstanding.

Note. Just between us, though, we’ll see what we can do. Pepperoni pizza OK with everyone?

Editor’s Note. No, we’re not sending pizza and/or beer to anyone. Sorry. (The part earlier that said the Scripting Editor is mean was completely accurate.)