Hey, Scripting Guy! How can I force a user to log off after 5 minutes of inactivity?
Hey, CS. You know, no doubt at least some of you are wondering why we Scripting Guys are so excited about the Winter Scripting Games (coming February 12-23, 2007 to a Script Center near you). What’s the deal here: do the Scripting Guys get a commission for each person who enters the Scripting Games?
Hmmm, that’s not a bad idea …. As it turns out, though, we don’t get any tangible reward for the Scripting Games; instead, we get excited about the Games for two reasons: 1) they’re fun; and, 2) at least two of the Scripting Guys thrive on competition, even if they aren’t the ones doing the competing. The truth is, several years ago, when we first became Scripting Guys, a lot of people looked upon scripting as being sheer drudgery. We see the Scripting Games as a way to show everyone that scripting is not only a useful tool for system administration, but it can be fun, too. What could be better than that?
But you want to know the real reason we like the Scripting Games? For once someone else has to do all the work! With the Scripting Games the tables are turned: this time we ask the questions and you have to write all the scripts. This is the one time of year when the Scripting Guys just kick back and relax and watch as everyone else work their fingers to the bone.
Well, come to think of it, we actually have to write these same scripts, too; after all, as the Games proceed we’ll publish sample solutions. And we have to write explanations that accompany each of these sample solutions. And, of course, we had to come up with all the events in the first place. And then there’s the official Scripting Games program and the training article. Oh: and we’re faced with the prospect of running and scoring hundreds and hundreds of scripts over the next couple weeks. And ….
On second thought, is it too late to cancel this year’s Scripting Games?
No, hey, we’re just kidding; the Scripting Games are by far the most fun thing we do all year. And yes, that includes performance reviews, changing offices, and those delightful three-hour “all-hands” meetings.
In fact, about the only thing we can think of that is more fun than the Scripting Games is a script that can log a user off a computer after 5 minutes of inactivity:
strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set objEventSource = objWMIService.ExecNotificationQuery _ ("SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'") Do While True Set objEventObject = objEventSource.NextEvent() If Right(objEventObject.TargetInstance.Name, 4) = ".scr" Then Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem") For Each objItem in colItems objItem.Win32Shutdown(4) Next End If Loop
Before we explain how this script works we should note that we cheated a little here. This is the kind of question we get asked quite a bit: how can you write a script that does something after a computer has been idle for x number of minutes? We understand why this is of interest to people; the only problem is that it’s not easy to determine – at least not by using a script – whether a computer is actually idle or not. Therefore, we decided the best thing to do was cheat: we don’t even bother trying to determine whether or not the computer is idle; instead, we let the computer make that determination for us.
How do we do that? Well, our script assumes that the screensaver has been configured to pop on if the computer has been idle for 5 minutes. Working under this assumption, we don’t have to decide whether or not the computer has been idle for 5 minutes; instead, we simply check periodically to see if the screensaver is running. If it is, then we assume that the computer has been idle for 5 minutes and we go ahead and log the user off.
In other words, “Let someone else do it.” Which would be a good motto for the Scripting Guys, wouldn’t it?
So then how do we determine whether or not the screensaver is running? Well, as you can see, the script starts off by connecting to the WMI service on the local computer (although you could also run this script against a remote computer). We then set up an event notification query that ventures out every 10 seconds and returns a list of all the processes running on the computer:Set objEventSource = objWMIService.ExecNotificationQuery _ ("SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'")
Note. You say you don’t know much about WMI events and event notification queries? That’s OK; this Scripting Guys webcast should answer all your questions.
After issuing our query we set up a Do While loop that’s designed to run forever. Inside that loop we use this line of code to instruct the script to wait until our event notification query actually notifies us of something:
Set objEventObject = objEventSource.NextEvent()
This line of code is going to cause the script to “block;” that is, it’s simply going to sit there until the query has some information for us. In this case, that’s going to occur every 10 seconds (that’s what the WITHIN 10 clause is for in the query): every 10 seconds our query will gather up a collection of running processes and hand them off to the script.
What we need to do next is determine whether the screensaver is included in that collection of running processes. That’s something we can do by looping through the collection and checking to see if the Name (the file name) of any process ends in .scr. That’s what we do here:
If Right(objEventObject.TargetInstance.Name, 4) = ".scr" Then
As you can see, we simply use the Right function to look at the last 4 letters in the file name. If those four letters happen to be .scr (for example, ssstars.scr) then we assume that the screensaver is running.
Note. Did you know that you can download your very own Script Center screensaver? Oh. Well, now you know.
Let’s assume that the screensaver is running. If so, we then issue a second QMI query, one designed to bind us to the Win32_OperatingSystem class:
Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
This query returns a collection consisting of the current operating system running on the computer. (Note that this doesn’t mean all the operating systems installed on the computer. If you have a multi-boot machine you’ll still get back just one item: the current operating system.) At that point we can then set up a For Each loop to loop through the collection and, for each operating system in the collection, call the Win32Shutdown method:
In case you’re wondering – and we know you are – the 4 simply tells the Win32Shutdown method to do a forced logoff. If you’d prefer to restart or completely shutdown a computer, well, that’s fine: Win32Shutdown accepts a number of different parameters. See the Microsoft Windows 2000 Scripting Guide for details.
And that should do it. Like we said, we cheated a little, but it works.
That’s a good question: if the Scripting Guys cheated does that mean that cheating is allowed in the Scripting Games? Listen, not only is cheating allowed, but cheating is encouraged: feel free to use any resources you can find that will help you complete the assigned tasks. In the case of the beginner events, for example, you can find Script Center scripts that will flat out solve some of the challenges for you: if you can copy and paste you can earn points in the Games. Remember, you don’t get any extra points for creativity or originality; you simply get points for submitting a solution that works.
Even better, if all you want is a chance at winning a prize your solution doesn’t even have to work; you just need to enter one of the events. In other words, with minimal effort you can send us a script that doesn’t do anything and yet still come out a winner. Now do you see why we Scripting Guys have such a soft spot in our hearts for the Scripting Games?