Windows PowerShell Tip of the Week
Here’s a quick tip on working with Windows PowerShell. These are published every week for as long as we can come up with new tips. If you have a tip you’d like us to share or a question about how to do something, let us know.
Modifying a Read-Write Property Using Get-WMIObject
So what’s your favorite Windows PowerShell cmdlet? Well, if you’re a system administrator, your favorite cmdlet is probably Get-WMIObject. After all, not only is Get-WMIObject (which enables you to access WMI from Windows PowerShell) the cmdlet of choice for carrying out system administration work, but Get-WMIObject is also one of the few Windows PowerShell 1.0 cmdlets that can be used against a remote computer. What’s not to like, right?
Well, at the risk of being picky, there is one thing: at first glance, it doesn’t appear as if you can use Get-WMIObject to modify the value of a read-write property. For example, take a look at this VBScript script, a script that changes the default value of the LoggingLevel property from 1 (on) to 0 (off):
Set objWMIService = GetObject("winmgmts:\\atl-fs-01\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * From Win32_WMISetting") For Each objItem in colItems objItem.LoggingLevel = 0 objItem.Put_ Next
As you can see, this is pretty straightforward: we simply assign the value 0 to the property LoggingLevel, then call the **Put_**method to save the new value to the operating system. Nothing could be simpler.
Now, let’s try this very same thing with Windows PowerShell:
$a = Get-WMIObject Win32_WMISetting -computername atl-fs-01 $a.LoggingLevel = 0 $a.Put_
If we run this script, it will run just fine, and without generating an error message. If we then take a peek at the value of the LoggingLevel property we’ll see that it – uh-oh:
Oh, dear, that’s not what we expected, not what we expected at all. Instead, we expected LoggingLevel to be equal to 0. Wait; we know what’s wrong. In Windows Powershell methods must be followed by a set of parentheses. Let’s change our last line of code to the following:
Now let’s re-run the script and see what happens:
Method invocation failed because [System.Management.ManagementObject#root\cimv2\Win32_WMISetting] doesn't contain a method named 'Put_'. At line:1 char:8 + $a.Put_( <<<< )
Hmmm, according to that error message there’s no such thing as the Put_ method. That’s odd; after all, VBScript doesn’t have any problem using the Put_ method. Oh, well, apparently you can’t modify the value of a read-write property using Windows PowerShell. Easy come, easy go. See you next week.
Wait, don’t go; this time we do know what the problem is. (Promise.) As it turns out, you can modify the value of a read-write property using Windows PowerShell just as easily as you can modify that value using VBScript. In fact, here’s some Windows PowerShell code that does just that:
$a = Get-WMIObject Win32_WMISetting -computername atl-fs-01 $a.LoggingLevel = 0 $a.Put()
So what did we do different here? Just one thing: we called the Put method rather than the Put_ method. That’s all we had to do. Just call the Put method, and you’ll be able to change the value of LoggingLevel (or any other read-write property) using Windows PowerShell.
Good question: why do we use the Put_ method in VBScript and the Put method in Windows PowerShell? Well, without going into too much detail, when you write a WMI script using VBScript you make use of WMI’s scripting API. In the scripting API, the SWbemObject object uses the Put_ method to save changes to a read-write property.
By contrast, Windows PowerShell accesses WMI through the .NET Framework and System.Management class. Rather than using SWbemObject, Windows PowerShell uses the System.Management.ManagementObject class. For better or worse, this class uses a method named Put to save changes to a read-write property. Ideally SWbemObject and System.Management.ManagementObject would use the same method names but, for some reason, they don’t.
But don’t worry too much about that. Just use Put in your Windows PowerShell scripts (and Put_ in your VBScript scripts) and we’ll all live happily ever after.