Hey, Scripting Guy! Question

Hey Scripting Guy! I have been playing with WMI on Windows PowerShell, and I think the Get-WmiObject cmdlet is pretty cool. It makes it easy to query for information from computers on my network. But what if I want to actually do something? How do I do that?

-- SH

Hey, Scripting Guy! AnswerHello SH,

Microsoft Scripting Guy Ed Wilson here. I completely understand your desire to do something. I am still a bit jet-lagged after my flight from Seattle (where I was speaking at the Microsoft TechReady conference) back to my home in Charlotte, North Carolina, in the United States. This trip took more than 12 hours to complete, and I did not get home until it was nearly 10:00 P.M. I then made a critical mistake: I went into my office at home and began working. Whoops. I did not retire for the evening until around 2:00 A.M. On Sunday, I stayed up working until nearly 3:30 A.M., and as a result I have not adjusted from my jet lag. Having spent five years traveling around the world teaching VBScript and Windows PowerShell workshops to customers, I know how to deal with jet lag, but knowing what to do and actually doing it are often two different things. Besides, I wanted to finish the experiments on the Windows 7 firewall I had begun on the plane (I wrote some pretty cool scripts). So I really feel the need to get out and do something. Let me think about your question while I sit here and sip a nice cup of hot English Breakfast tea.

Well, SH, I feel much better. I have finished my first cup of English Breakfast tea (with a stick of Ceylon and a piece of lemon grass in it). I have turned on John Cafferty on my Zune, and I am starting to feel human. When I go swimming this afternoon, I will be back to my normal cheerful self. Speaking of doing something, you did not mention what that something should be. I will therefore exercise some liberty in answering your question.

Normally when we think about "doing something," we are referring to calling a method. When we think about obtaining information about something, we are referring to reading a property. When we use the Get-WmiObject cmdlet, by default we are returning information about something. We are returning the properties of objects. Each of the WMI classes represents something on our computer. For example, there is the WMI class that is named Win32_PointingDevice that is used to represent a mouse on the computer. Properties of a mouse are things like number of buttons, a right-handed or a left-handed mouse, double-click speed, and things like that. The easy way to determine the properties of a mouse is to use the Get-WmiObject cmdlet and pipe the output to the Format-List cmdlet. When you do this, make sure you choose all the properties. This is seen here.

PS C:\> Get-WmiObject -Class win32_pointingdevice | Format-List -Property *


__GENUS                     : 2
__CLASS                     : Win32_PointingDevice
__SUPERCLASS                : CIM_PointingDevice
__DYNASTY                   : CIM_ManagedSystemElement
__RELPATH                   : Win32_PointingDevice.DeviceID="ACPI\\PNP0F13\\4&1
                              506BB2E&0"
__PROPERTY_COUNT            : 33
__DERIVATION                : {CIM_PointingDevice, CIM_UserDevice, CIM_LogicalD
                              evice, CIM_LogicalElement...}
__SERVER                    : OFFICE
__NAMESPACE                 : root\cimv2
__PATH                      : \\OFFICE\root\cimv2:Win32_PointingDevice.DeviceID
                              ="ACPI\\PNP0F13\\4&1506BB2E&0"
Availability                :
Caption                     : PS/2 Compatible Mouse
ConfigManagerErrorCode      : 0
ConfigManagerUserConfig     : False
CreationClassName           : Win32_PointingDevice
Description                 : PS/2 Compatible Mouse
DeviceID                    : ACPI\PNP0F13\4&1506BB2E&0
DeviceInterface             : 4
DoubleSpeedThreshold        : 6
ErrorCleared                :
ErrorDescription            :
Handedness                  : 2
HardwareType                : PS/2 Compatible Mouse
InfFileName                 : msmouse.inf
InfSection                  : PS2_Inst
InstallDate                 :
IsLocked                    :
LastErrorCode               :
Manufacturer                : Microsoft
Name                        : PS/2 Compatible Mouse
NumberOfButtons             : 3
PNPDeviceID                 : ACPI\PNP0F13\4&1506BB2E&0
PointingType                : 2
PowerManagementCapabilities :
PowerManagementSupported    : False
QuadSpeedThreshold          : 10
Resolution                  :
SampleRate                  :
Status                      : OK
StatusInfo                  :
Synch                       :
SystemCreationClassName     : Win32_ComputerSystem
SystemName                  : OFFICE

As you look through the output, you will notice that some of the properties do not return any information. This is typical behavior for WMI. Often the properties that do not return any information have been inherited from other classes. The great thing about using the Get-WmiObject cmdlet is that it quickly and easily makes it possible to see if a property from a WMI class returns any information. You can use the Windows PowerShell Scriptomatic to quickly build WMI scripts using Windows PowerShell. Similar in concept and functionality to the original Scriptomatic, the Windows PowerShell Scriptomatic lists WMI classes and allows you to select the class and to create a Windows PowerShell script that will retrieve the properties from that class. This is seen here:

Image of the Windows PowerShell Scriptomatic


You can take the results of the Get-WmiObject cmdlet and pipe it to the Get-Member cmdlet. When you do this, you will see both methods and properties returned by command. You will also notice that all the properties state they are {get ; set},  which might make you think that you can both read and write to the properties. This is seen here:

Image of the properties all being {get ; set}

 

Because all the properties are specified as {get ; set}, it should clue you in that you cannot actually change things such as the NumberOfButtons on your mouse by making a change to the property value. So, you might ask, is the Get-Member cmdlet "lying” to us? To see if Get-Member is lying to us, we perform a small test. First we will query the Win32_PointingDevice class and store the results in a variable called $mouse. Next we will assign a new value to the property, and then we will query the property. This is seen here:

PS C:\>  $mouse.NumberOfButtons
12
PS C:\>  $mouse = Get-WmiObject -Class win32_pointingdevice
PS C:\>  $mouse.NumberOfButtons = 12
PS C:\>  $mouse.NumberOfButtons
12


The first time I did this, I expected it to throw an error, but it actually works. Of course when I look at my mouse, it did not grow additional buttons or morph into some kind of bizarre transformer creature and spring from my office window to go fight the forces of evil. (Scripting Editor: That would have been wicked cool. Please work on making this happen for a future article.) As a matter of fact, it did not even move. So clearly the property is read only. We can verify this by using the WMI Tester (WbemTest.exe). To do this, we type WbemTest inside our Windows PowerShell console. The WMI Tester appears. On Windows Vista and later, the default namespace of Root\Cimv2 will already be set for you. On earlier versions of WbemTest (pronounced "web um test"), you will need to type root\cimv2 in the namespace dialog box and press Connect. Use the Open Class button (third button down in the first column) to open the Win32_PointingDevice WMI class. The Object Editor for Win32_PointingDevice appears. In the Properties area (big box in the middle of the Object Editor), scroll down until you see the NumberOfButtons property. This is seen in here:

Image of the NumberOfButtons property in the Object Editor

After you have found the NumberOfButtons property, double-click it to open the Property Editor. In the Qualifiers area, you can see that the property has the read qualifier, but not the write qualifier. This means that the property is read-only. This is seen here:

Image of Property Editor of NumberOfButtons property

Additional examples of using the WMI Tester can be seen in earlier Hey, Scripting Guy! blog postings. Whenever I need to see exactly what WMI is doing, I fire up WbemTest. I will not say it is my favorite tool, but it is one of the more powerful tools I have for working with WMI.

Oh, by the way, you should be very careful when using WbemTest. There is a very good reason the dialogs seen earlier are called Object Editor and Property Editor. Think of WbemTest as being the Registry Editor for WMI. This tool is read/write and allows you to actually edit the WMI classes and change their behavior, which could break all kinds of things. Be very careful!

SH, I have not forgotten about your original question. You want to do stuff. So why did I spend all this time talking about properties? Because a number of the properties of a number of WMI classes are actually read/write, they provide you with the ability to make changes and to do stuff. As an example, you can change the amount of time that the list of operating systems is displayed by modifying the value of the SystemStartUpDelay property from the Win32_ComputerSystem WMI class. To write the change property value back to WMI, you use the put method. This is seen here:

PS C:\> $computer = Get-WmiObject -Class win32_computersystem
PS C:\> $computer.SystemStartupDelay
30
PS C:\> $computer.SystemStartupDelay = 15
PS C:\> $computer.put()


Path          : \\localhost\root\cimv2:Win32_ComputerSystem.Name="OFFICE"
RelativePath  : Win32_ComputerSystem.Name="OFFICE"
Server        : localhost
NamespacePath : root\cimv2
ClassName     : Win32_ComputerSystem
IsClass       : False
IsInstance    : True
IsSingleton   : False

Well, SH, we hope you enjoyed this excursion into WMI. Because Windows PowerShell makes it so easy to work with WMI, this actually frees you up to spend more time looking at how you can use this technology. If you are interested in learning more about WMI, check out the Microsoft Press book or some of the other learning resources we have on the Learn page of the Script Center. If you want to be the first to know what is going on on the Script Center, follow us on Twitter or on Facebook. If you need assistance with a script, you can post questions to the Official Scripting Guys Forum, or send e-mail to scripter@microsoft.com. WMI Week will continue tomorrow as we look at calling methods to do things. See you tomorrow. Peace!

Ed Wilson and Craig Liebendorfer, Scripting Guys