December 9th, 2009

Hey, Scripting Guy! How Can I Use WMI to Set the Screen Saver Timeout Value on Workstations?

Bookmark and Share   

 

Hey, Scripting Guy! Question

Hey Scripting Guy! I have been trying to set the screen saver time out value on my workstations by using WMI. It is not working. Can you help me get WMI working?

— HR

 

Hey, Scripting Guy! AnswerHello HR,

Microsoft Scripting Guy Ed Wilson here. My teapot is empty. I was getting ready to head downstairs to fix me a nice pot of Constant Comment tea, but Outlook dinged at me signaling that your e-mail had arrived in the scripter@microsoft.com alias. I love it when an e-mail is short, sweet, and to the point. Because I get several hundred e-mail messages a week. Long, convoluted messages tend to get shuffled to the bottom of the pile. Eventually, they get answered, but short ones are easier to deal with. The short answer is that WMI is probably already working just fine. The problem is that it does not allow you to modify the screen saver timeout value.

Note: Portions of today’s Hey, Scripting Guy! post are excerpted from the Microsoft Press book, Windows PowerShell 2.0 Best Practices by Ed Wilson, which is now available for pre-order.

For all the good things to be had with WMI, there are still a number of very frustrating limitations. For example, WMI is good at retrieving information, but it is not always very good at changing that information. Here is an example that illustrates the point. The Win32_Desktop WMI class provides information about desktop settings as seen here.

PS C:> Get-WmiObject Win32_Desktop


__GENUS               : 2
__CLASS               : Win32_Desktop
__SUPERCLASS          : CIM_Setting
__DYNASTY             : CIM_Setting
__RELPATH             : Win32_Desktop.Name=”NT AUTHORITY\SYSTEM”
__PROPERTY_COUNT      : 21
__DERIVATION          : {CIM_Setting}
__SERVER              : MRED1
__NAMESPACE           : rootcimv2
__PATH                : \MRED1rootcimv2:Win32_Desktop.Name=”NT AUTHORITY\SY
                        STEM”
BorderWidth           : 1
Caption               :
CoolSwitch            :
CursorBlinkRate       : 500
Description           :
DragFullWindows       : True
GridGranularity       :
IconSpacing           :
IconTitleFaceName     : Segoe UI
IconTitleSize         : 9
IconTitleWrap         : True
Name                  : NT AUTHORITYSYSTEM
Pattern               : (None)
ScreenSaverActive     : True
ScreenSaverExecutable : C:Windowssystem32logon.scr
ScreenSaverSecure     : True
ScreenSaverTimeout    : 600
SettingID             :
Wallpaper             :
WallpaperStretched    : False
WallpaperTiled        :

 

As you can see from the properties and values that are returned from the Get-WmiObject cmdlet, much of the information is valuable. Items such as screen saver timeout values and secure screen saver are of routine concern to many network administrators. While it is true these values can, and in most cases should, be set via Group Policy, there are times when network administrators want the ability to change these values via script. If you use the Get-Member cmdlet to examine the properties of the Win32_Desktop WMI class, you will be greeted with the following information.

PS C:> Get-WmiObject Win32_Desktop | Get-Member


   TypeName: System.Management.ManagementObject#rootcimv2Win32_Desktop

Name                  MemberType   Definition
—-                  ———-   ———-
BorderWidth           Property     System.UInt32 BorderWidth {get;set;}
Caption               Property     System.String Caption {get;set;}
CoolSwitch            Property     System.Boolean CoolSwitch {get;set;}
CursorBlinkRate       Property     System.UInt32 CursorBlinkRate {get;set;}
Description           Property     System.String Description {get;set;}
DragFullWindows       Property     System.Boolean DragFullWindows {get;set;}
GridGranularity       Property     System.UInt32 GridGranularity {get;set;}
IconSpacing           Property     System.UInt32 IconSpacing {get;set;}
IconTitleFaceName     Property     System.String IconTitleFaceName {get;set;}
IconTitleSize         Property     System.UInt32 IconTitleSize {get;set;}
IconTitleWrap         Property     System.Boolean IconTitleWrap {get;set;}
Name                  Property     System.String Name {get;set;}
Pattern               Property     System.String Pattern {get;set;}
ScreenSaverActive     Property     System.Boolean ScreenSaverActive {get;set;}
ScreenSaverExecutable Property     System.String ScreenSaverExecutable {get;…
ScreenSaverSecure     Property     System.Boolean ScreenSaverSecure {get;set;}
ScreenSaverTimeout    Property     System.UInt32 ScreenSaverTimeout {get;set;}
SettingID             Property     System.String SettingID {get;set;}
Wallpaper             Property     System.String Wallpaper {get;set;}
WallpaperStretched    Property     System.Boolean WallpaperStretched {get;set;}
WallpaperTiled        Property     System.Boolean WallpaperTiled {get;set;}
__CLASS               Property     System.String __CLASS {get;set;}
__DERIVATION          Property     System.String[] __DERIVATION {get;set;}
__DYNASTY             Property     System.String __DYNASTY {get;set;}
__GENUS               Property     System.Int32 __GENUS {get;set;}
__NAMESPACE           Property     System.String __NAMESPACE {get;set;}
__PATH                Property     System.String __PATH {get;set;}
__PROPERTY_COUNT      Property     System.Int32 __PROPERTY_COUNT {get;set;}
__RELPATH             Property     System.String __RELPATH {get;set;}
__SERVER              Property     System.String __SERVER {get;set;}
__SUPERCLASS          Property     System.String __SUPERCLASS {get;set;}
ConvertFromDateTime   ScriptMethod System.Object ConvertFromDateTime();
ConvertToDateTime     ScriptMethod System.Object ConvertToDateTime();

 

When you use the filter parameter to get a specific instance of the Win32_Desktop WMI class and store it in a variable, you can directly access the properties of the class. In this example we need to escape the backward slash that is used as a separator between NT Authority and System. This is shown here.

PS C:> $desktop = Get-WmiObject Win32_Desktop -Filter `

>> “name = ‘NT AUTHORITY\SYSTEM'”

 

After you have access to a specific instance of the WMI class, you can assign a new value for the ScreenSaverTimeout parameter. As shown here, the value is updated immediately:

PS C:> $Desktop.ScreenSaverTimeout = 300

PS C:> $Desktop.ScreenSaverTimeout

300

 

However, if you resubmit the WMI query, you will see that the ScreenSaverTimeout property was not updated. The get:set that is reported by the Get-Member cmdlet is related to the copy of the object that is returned by the WMI query, and not to the actual instance of the object represented by the WMI class. This is seen here:

PS C:> $desktop = Get-WmiObject Win32_Desktop -Filter `
>> “name = ‘NT AUTHORITY\SYSTEM'”
>>
PS C:> $Desktop.ScreenSaverTimeout
600

 

To set the screen saver timeout value, you will need to edit the registry. The GetSetScreenSaverTimeOut.ps1 script uses the Set-ItemProperty cmdlet to assign a new value to the ScreenSaverTimeout registry key. The GetSetScreenSaverTimeOut.ps1 script accepts two command-line parameters. The first parameter is a debug switch, and the second is the new screen saver timeout value you wish to set.

The Get-ItemProperty cmdlet is used to read the current value of the screen saver timeout value from the registry. It accepts the path to the registry key and the name of the registry property. The Get-RegistryValue function calls the Get-ItemProperty cmdlet and stores the returned value in the $in reference variable. The Get-RegistryValue function is seen here:

Function Get-RegistryValue([ref]$in)
{
 Write-Debug $MyInvocation.MyCommand.name
 $in.value = (Get-ItemProperty -path $path -name $name).$name
} #end Get-RegistryValue

 

The Set-ItemProperty cmdlet accepts the path to the registry key, the name of the registry property to modify, and the new value to assign to the registry key. This is seen in the Set-RegistryValue function:

Function Set-RegistryValue($value)
{
 Write-Debug $MyInvocation.MyCommand.name
 Set-ItemProperty -Path $path -name $name -value $value
} #end Get-RegistryValue

 

The Write-Feedback function is used to display the value stored in the screen saver timeout registry key. This function is seen here:

Function Write-Feedback($in)
{
 Write-Debug $MyInvocation.MyCommand.name
 “The $name is set to $($in)”
} #end Write-Feedback

 

If the script is run with the –debug switch, the Write-Debug cmdlet will display additional information on the screen. This is seen here:

Image of Write-Debug cmdlet displaying additional information on screen

 

The complete GetSetScreenSaverTimeOut.ps1 script is seen here.

GetSetScreenSaverTimeOut.ps1

Param([switch]$debug, $value = 120)
Function Get-RegistryValue([ref]$in)
{
 Write-Debug $MyInvocation.MyCommand.name
 $in.value = (Get-ItemProperty -path $path -name $name).$name
} #end Get-RegistryValue

Function Set-RegistryValue($value)
{
 Write-Debug $MyInvocation.MyCommand.name
 Set-ItemProperty -Path $path -name $name -value $value
} #end Get-RegistryValue

Function Write-Feedback($in)
{
 Write-Debug $MyInvocation.MyCommand.name
 “The $name is set to $($in)”
} #end Write-Feedback

# *** Entry Point ***
if($debug) { $DebugPreference = “continue” }
$path = ‘HKCU:Control PanelDesktop’
$name = ‘ScreenSaveTimeOut’
$in = $null

Get-RegistryValue([ref]$in)
Write-Feedback($in)
Set-RegistryValue($value)
Get-RegistryValue([ref]$in)
Write-Feedback($in)

 

HR, that is all there is to setting the screen saver timeout value. WMI Week will continue tomorrow.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Author

0 comments

Discussion are closed.