Problem
You want to perform a WMI task in PowerShell, but can find only VBScript examples that demonstrate the solution to the problem.
Solution
To accomplish the task of a script that retrieves data from a computer, use the GetWmiObject cmdlet: foreach($printer in GetWmiObject –Computer COMPUTER Win32_Printer) { ## Work with the properties $printer.Name
} To accomplish the task of a script that calls methods on an instance, use the [Wmi] or [WmiSearcher] accelerators to retrieve the instances, and then call methods on the instances like you would call any other PowerShell method:
$service = [Wmi] 'Win32_Service.Name="winmgmt"'
$service.ChangeStartMode("Manual")
$service.ChangeStartMode("Automatic")
To accomplish the task of a script that calls methods on a class, use the [WmiClass] accelerator to retrieve the class, and then call methods on the class like you would call any other PowerShell method:
$class = [WmiClass] "Win32_Process"
$class.Create("Notepad")
Discussion
For many years, VBScript has been the preferred language that administrators use to access WMI data. Because of that, the vast majority of scripts available in books and on the Internet come written in VBScript.
These scripts usually take one of three forms: retrieving data and accessing properties, calling methods of an instance, and calling methods of a class.
Although most WMI scripts on the Internet accomplish unique tasks, PowerShell supports many of the traditional WMI tasks natively. If you want to translate a WMI example to PowerShell, first check that
there aren’t any PowerShell cmdlets that might accomplish the task directly.
Retrieving data
One of the most common uses of WMI is for data collection and system inventory tasks. A typical VBScript that retrieves data looks like Example 153.
Example 153. Retrieving printer information from WMI using VBScript
strComputer = "." Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colInstalledPrinters = objWMIService.ExecQuery _ ("Select * from Win32_Printer")
For Each objPrinter in colInstalledPrinters Wscript.Echo "Name: " & objPrinter.Name Wscript.Echo "Location: " & objPrinter.Location Wscript.Echo "Default: " & objPrinter.Default
Next
The first three lines prepare a WMI connection to a given computer and namespace. The next two lines of code prepare a WMI query that requests all instances of a class. The For Each block loops over all the instances, and the objPrinter.Property statements interact with properties on those instances.
In PowerShell, the GetWmiObject cmdlet takes care of most of that, by retrieving all instances of a class from the computer and namespace that you specify. The first five lines of code then become:
$installedPrinters = GetWmiObject Win32_Printer If you need to specify a different computer, namespace, or query restriction, the GetWmiObject cmdlets supports those through optional parameters.
In PowerShell, the For Each block becomes: foreach($printer in $installedPrinters) { $printer.Name $printer.Location $printer.Default }
Notice that we spend the bulk of the PowerShell conversion of this script showing how to access properties. If you don’t actually need to work with the properties (and only want to display them for reporting purposes), PowerShell’s formatting commands simplify that even further:
GetWmiObject Win32_Printer | FormatList Name,Location,Default
Calling methods on an instance
Although data retrieval scripts form the bulk of WMI management examples, another common task is to call methods of an instance that invoke actions.
For example, Example 154 changes the startup type of a service.
Example 154. Changing the startup type of a service from WMI using VBScript
strComputer = "." Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colServiceList = objWMIService.ExecQuery _ ("Select * from Win32_Service where StartMode = 'Manual'")
For Each objService in colServiceList
errReturnCode = objService.ChangeStartMode("Disabled") Next
The first three lines prepare a WMI connection to a given computer and namespace. The next two lines of code prepare a WMI query that requests all instances of a class and adds an additional filter (StartMode = 'Manual') to the query. The For Each block loops over all the instances, and the objService.Change(...) statement calls the Change() method on the service.
In PowerShell, the GetWmiObject cmdlet takes care of most of the setup, by retrieving all instances of a class from the computer and namespace that you specify. The first five lines of code then become:
$services = GetWmiObject Win32_Service –Filter "StartMode = 'Manual'" If you need to specify a different computer or namespace, the GetWmiObject cmdlets supports those through optional parameters.
In PowerShell, the For Each block becomes: foreach($service in $services) { $service.ChangeStartMode("Disabled") }
Calling methods on a class
Although less common than calling methods on an instance, it is sometimes helpful to call methods on a WMI class. PowerShell makes this work almost exactly like calling methods on an instance.
For example, a script that creates a process on a remote computer looks like this:
strComputer = "COMPUTER"
Set objWMIService = GetObject _
("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")
objWMIService.Create("notepad.exe")
The first three lines prepare a WMI connection to a given computer and namespace. The final line calls the Create() method on the class.
In PowerShell, the [WmiClass] accelerator lets you easily access WMI classes. The first three lines of code then become:
$processClass = [WmiClass] "\\COMPUTER\Root\Cimv2:Win32_Process"
In PowerShell, calling the method on the class is nearly identical:
$processClass.Create("notepad.exe")