We are pretty well annoyed at you guys. We spent all this time and energy creating all these VBScripts over the last nine years. We have several hundred VBScripts that we use in production, and with uncertain economic times, you are now telling me I have to rewrite all these scripts in Windows PowerShell? Most of these scripts use WMI, which, if you were honest and would admit it, has a rather convoluted syntax, and I do not relish the idea of going through that again. Some of those queries literally took me more than a week of futzing around to get the thing to work. I would rather get a root canal than go through that again.
– VT
Hi VT,
You caught me on a rather unusual day. I am drinking coffee this morning. Probably because I was up till nearly midnight planning the editorial calendar to the end of the fiscal year. Anyway, when I drink coffee, it is Peaberry beans I bring back from the island of Hawaii (also known as the Big Island). I grind the beans in my coffee grinder and place them gently into my French press, which allows for the enjoyment of full flavor. I then warm my cream in the microwave for exactly 60 seconds on medium. I heat my coffee mug by filling it with water, and microwaving it on high for 60 seconds. By this time, the freshly drawn spring water has heated in my water kettle that I fell in love with while I was in Paris a few years ago. (That is Paris, France, and not Paris, Kentucky.) I use half a spoon of Turbinado I brought back from Maui, Hawaii, to sweeten my cup of coffee. To me there is just no point in drinking an inferior cup of coffee.
Why the discussion of coffee? Because, VT, it seems to me you need to lay off the caffeine. Next time you go get a cup of Joe, grab the pot with the green handle. I can certainly sympathize with your dilemma, but there are few things in life worth getting too excited about. Repeat after me: “Serenity now.” In this particular case there is absolutely nothing to get upset about. Nothing at all, because VBScript is going to be in Windows 7, and it is also in Windows Server 2008 R2. If you have a perfectly working VBScript that does everything you want it to do, there is absolutely no reason to get rid of it. I do believe you should be learning Windows PowerShell, however, because it is extremely powerful and is central to our management story moving forward. Windows 7 and Windows Server 2008 R2 both have Windows PowerShell 2.0 built in, and there are many easy-to-use cmdlets included in both platforms that will greatly simplify common administrative tasks moving forward. The time to learn Windows PowerShell is when you have time to think about it, not at 2:00 A.M. when the server is down and you are wondering how to remote into it.
I did run across one company in Frankfurt, Germany, last year that had decided to migrate all their existing VBScripts to Windows PowerShell. They only wanted to support a single scripting platform. Pretty cool, but most companies do not have that luxury. But suppose you do decide to migrate your VBScript WMI queries to Windows PowerShell. How would you go about it? I am finished with my perfect cup of coffee, so let’s roll up our sleeves and get to work.
This week we will be looking at working with WMI from within Windows PowerShell. In honor of this week, we have created a new WMI Scripting Hub that pulls together a number of useful articles and tools from all over the Script Center into a single location. Because the articles will be using Windows PowerShell, you may also be interested in the Windows PowerShell Scripting Hub. You will find information there that will tell you how to download and install Windows PowerShell. |
The Get-WmiObject cmdlet in Windows PowerShell has the –query parameter. We can use the –query parameter to supply a WMI Query language (WQL) syntax to the get-WmiObject cmdlet. This makes it easy to transfer your investment in complicated WMI queries you may have written for VBScript directly into Windows PowerShell.
Suppose we have the List Printer Drivers script. The ListPrinterDrivers.vbs script is seen here:
strComputer = "." Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Set colInstalledPrinters = objWMIService.ExecQuery _ ("Select * from Win32_PrinterDriver") For each objPrinter in colInstalledPrinters Wscript.Echo "Configuration File: " & objPrinter.ConfigFile Wscript.Echo "Data File: " & objPrinter.DataFile Wscript.Echo "Description: " & objPrinter.Description Wscript.Echo "Driver Path: " & objPrinter.DriverPath Wscript.Echo "File Path: " & objPrinter.FilePath Wscript.Echo "Help File: " & objPrinter.HelpFile Wscript.Echo "INF Name: " & objPrinter.InfName Wscript.Echo "Monitor Name: " & objPrinter.MonitorName Wscript.Echo "Name: " & objPrinter.Name Wscript.Echo "OEM Url: " & objPrinter.OEMUrl Wscript.Echo "Supported Platform: " & objPrinter.SupportedPlatform Wscript.Echo "Version: " & objPrinter.Version Next
The WQL query in the ListPrinterDrivers.vbs script is passed to the ExecQuery method. The query is this string:
Select * from Win32_PrinterDriver
We can use the WQL query directly with Get-WmiObject as seen here:
Get-WmiObject -Query "Select * from Win32_PrinterDriver"
When we run the above command, we are treated to an output that displays the same information that is provided with the ListPrinterDrivers.vbs script. The WQL query was the same, so it stands to reason the same information would be returned from WMI. The results of the command are seen here:
While everything is currently groovy (I am as a matter of fact listening to Take Five by Dave Brubeck), there is really no reason to use the –query parameter with the Get-WmiObject cmdlet when the query is in the Select everything from the class format as seen here:
Select * from whateverwmiclass
The reason is that the when you use Select * from the class, you can obtain the same information more easily by using the –class parameter and no filter as seen here:
Get-WmiObject –Class Win32_PrinterDriver
Suppose you have a script such as ListDiskFreeSpace.vbs:
strComputer = "." Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Set colDisks = objWMIService.ExecQuery _ ("Select * from Win32_LogicalDisk Where DriveType = 3") For Each objDisk in colDisks Wscript.Echo "DeviceID: "& vbTab & objDisk.DeviceID Wscript.Echo "Free Disk Space: "& vbTab & objDisk.FreeSpace Next
The query section in the ListDiskFreeSpace.vbs script can be “stolen” from the ListPrinterDrivers.vbs script and used directly:
Get-WmiObject -Query "Select * from Win32_LogicalDisk Where DriveType = 3"
When we run the script, we are greeted with the information seen here:
Now, let’s take a look at something that can be incredibly difficult: the Associators Of query. This script is referenced in this article:
strComputer = "." Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Set colShares = objWMIService.ExecQuery _ ("ASSOCIATORS OF {Win32_Share.Name='Scripts'} WHERE " _ & "AssocClass=Win32_ShareToDirectory") For Each objFolder in colShares Wscript.Echo objFolder.Name Next
The Associators Of query seen in the AssociatorsOfShareToFolder.vbs is shown here:
"ASSOCIATORS OF {Win32_Share.Name='Scripts'} WHERE AssocClass=Win32_ShareToDirectory"
To get the query into the pattern above, we deleted the closing quote and underscore from the first line, and deleted the ampersand and quote from the second line. It will provide the mapping between a shared folder named scripts and the directory name associated with the share. The problem with writing Associators Of queries is they are really finicky in regards to placements of quotation marks, curly brackets, and the like. This is definitely a situation where we want to leverage the development effort already done. Once again, we paste the code into the query parameter (the below code is a single line):
Get-WmiObject -Query "ASSOCIATORS OF {Win32_Share.Name='Scripts'} WHERE` AssocClass=Win32_ShareToDirectory"
When we run the script, we are cheerfully greeted with the output seen here:
That was pretty fun. Let’s try our luck once again and see what happens. Suppose you have a VBScript that you use to retrieve files and their version numbers from a particular folder. You would like to migrate it to Windows PowerShell. Such a script is referenced in this “Hey, Scripting Guy!” article:
strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colFileList = objWMIService.ExecQuery _ ("ASSOCIATORS OF {Win32_Directory.Name='C:\Windows\System32'} Where " _ & "ResultClass = CIM_DataFile") For Each objFile In colFileList If objFile.Extension = "dll" Then Wscript.Echo objFile.Name & " -- " & objFile.Version End If Next
The Associators Of query from the ListFilesAndVersion.vbs script is seen here:
"ASSOCIATORS OF {Win32_Directory.Name='C:\Windows\System32'} Where " _ & "ResultClass = CIM_DataFile"
Once again, because the Associators Of query was rather long, it was broken into two lines of code. We need to remove the closing quotation mark and underscore from the first line, and the ampersand and opening quotation mark from the second line. The cleaned up query is seen here:
"ASSOCIATORS OF {Win32_Directory.Name='C:\Windows\System32'} Where ResultClass = CIM_DataFile"
We open our Windows PowerShell console, use the Get-WmiObject cmdlet with the –query parameter, and paste the Associators Of query directly into the command line. This is seen here (remember this command has wrapped; it is a single command):
Get-WmiObject -Query "ASSOCIATORS OF {Win32_Directory.Name='C:\Windows\System32'}` Where ResultClass = CIM_DataFile"
We are again greeted with success. The output on my computer is seen here:
See, VT, there is nothing to get excited about. In fact, I am not sure how to say this other than to just come on out and say it. Using the –query parameter with the Get-WmiObject cmdlet is a heck of a lot better for your mental hygiene than saying “Serenity now!” WMI Week continues to roll on, and we have yet to write a script. Three down and one to go, see you tomorrow for the exciting conclusion of WMI Wweek. Until then, be mellow (Dave Brubeck is now playing “The Duke”; yeah, baby).
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments