Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I tell if the screen saver is active and, if so, how long it has been running?

-- MS

SpacerHey, Scripting Guy! AnswerScript Center

Hey, MS. Interesting question; we don’t think we’ve ever been asked that before. And at first it had us stumped; after all, there aren’t any WMI classes or COM objects for managing the screen saver, and we didn’t know of any event that was fired each time a screen saver kicked in, at least not an event we could get to using a script. This had all the makings of a complex and complicated problem that would likely take us years to solve.

Or, as it turned out, it was something we could solve in just a couple minutes:

strComputer = "atl-dc-01"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("Select * from Win32_Process")

For Each objProcess in colProcesses
    If Right(objProcess.Name, 4) = ".scr" Then
        Wscript.Echo "The screen saver " & objProcess.Name & " is running."
        Wscript.Echo "Screen saver start time: " & objProcess.CreationDate
        Wscript.Quit
    End If
Next

Wscript.Echo "The screen saver is not running."

To be honest, we were originally making a mountain out of a molehill. Granted, there are no COM objects for managing the screen saver and there are no events fired when the screen saver kicks in. But that’s OK. When the screen saver runs, it typically runs a file with a .scr file extension. If we want to know whether or not the screen saver is running all we have to do is check and see if there are any processes running that have an executable name ending in .scr. If there are, that probably means the screen saver is running.

Note. We’re aware that this isn’t foolproof and there might be third-party screen savers that use a different file extension. But this approach should work for any of the screen savers that ship with the operating system.

Now that we understand the strategy let’s take a look at the script. For one thing, you might notice that the first line of code is a little different from most of our sample WMI scripts:

strComputer = "atl-dc-01"

Typically our first line of code sets the value of the variable strComputer to a dot (.); we do that because the dot represents the local computer, and setting strComputer to a dot gives us a script that will run on the local computer regardless of the name of that computer. We’re assuming, however, that you want to run this script against a remote machine; there are probably easier ways to tell whether or not the screen saver is running on your local machine without going to the trouble of writing a script. Therefore we set the value of strComputer to the name of a remote computer, in this case atl-dc-01.

Next we connect to the Win32_Process class and use the ExecQuery method to retrieve a collection of all the processes running on the computer atl-dc-01. We then set up a For Each loop to cycle through that collection. Inside the loop we check the value of the Name property for each process (this will be equivalent to the file name for the application). If the Name ends in .scr we assume that a screen saver is running; we then echo the executable file name for the screen saver as well as the time that the screen saver started running. (We can retrieve that value from the CreationDate property.) Having found the screen saver, we then call the Wscript.Quit method to exit the script.

How do we know if the executable file name ends in .scr? We simply use the VBScript Right function, and tell it to check the last four characters in the string:

If Right(objProcess.Name, 4) = ".scr" Then

But what if we don’t find a process whose Name ends in .scr? After checking each and every process, we exit the loop and then echo a message stating that the screen saver is not running.

When we run the script, we get back output similar to this:

The screen saver logon.scr is running.
Screen saver start time: 20050725153639.115344-420

Well, yes, that’s a good point: the start time comes back in UTC (Universal Time Coordinate) format, which isn’t the most intuitive date-time format ever created. Therefore, let’s modify our script to include a function that convert this UTC date-time into something a bit more readable:

strComputer = "atl-dc-01"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("Select * from Win32_Process")

For Each objProcess in colProcesses
    If Right(objProcess.Name, 4) = ".scr" Then
        Wscript.Echo "The screen saver " & objProcess.Name & " is running."
        dtmStartTime = objProcess.CreationDate
        dtmScreensaverStart = WMIDateStringToDate(dtmStartTime)
        Wscript.Echo "Screen saver start time: " & dtmScreensaverStart
        Wscript.Quit
    End If
Next

Wscript.Echo "The screen saver is not running."

Function WMIDateStringToDate(dtmBootup)
    WMIDateStringToDate = CDate(Mid(dtmBootup, 5, 2) & "/" & _
        Mid(dtmBootup, 7, 2) & "/" & Left(dtmBootup, 4) _
            & " " & Mid (dtmBootup, 9, 2) & ":" & _
                Mid(dtmBootup, 11, 2) & ":" & Mid(dtmBootup,13, 2))
End Function

When we run this script we get back output that’s a little easier to parse:

The screen saver logon.scr is running.
Screen saver start time: 7/25/2005 3:36:39 PM

Note. We won’t discuss the function for converting a UTC date to a regular date, but you can read about the process in this section of the Microsoft Windows 2000 Scripting Guide.

Like we said, determining whether or not the screen saver is running turned out to be fairly easy. Which makes us wonder whether people have been making this cold fusion thing much tougher than it should be….