Chapter 28. Windows Management Instrumentation

Introduction

Windows Management Instrumentation (WMI) has long been a core management feature in Windows. It offers amazing breadth, wide reach, and ubiquitous remoting.

What WMI lacked in the past, though, was a good way to get to it. Graphically, the wbemtest.exe utility lets you experiment with WMI, its namespaces, and classes. It truly is a testing tool, though, as its complex user interface makes it impractical to use for most scenarios (see Figure 28-1).

Using wbemtest.exe to retrieve a Win32_Process

Figure 28-1. Using wbemtest.exe to retrieve a Win32_Process

A more user-friendly alternative is the wmic.exe command-line tool. The WMIC tool lets you interactively query WMI—but more importantly, automate its behavior. As with PowerShell, results within WMIC retain a great deal of their structured information and let you write fairly detailed queries:

PS > WMIC logicaldisk WHERE drivetype=3 `
    GET "name,freespace,SystemName,FileSystem,Size"

FileSystem  FreeSpace    Name  Size         SystemName
NTFS        10587656192  C:    34357637120  LEEHOLMES1C23

The language is limited, however, and all of the data’s structure is lost once WMIC converts its output to text.

By far, the most popular user interface for WMI has been VBScript, the administrator’s traditional scripting language. VBScript offers much richer language facilities than WMIC and retains WMI’s structured data for the entire duration of your script.

VBScript has its own class of usability difficulties, however. For example, generating a report of the processes running on a computer often ends up looking like this:

strComputer = "atl-dc-01"
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\" _
    & strComputer & "
ootcimv2")
Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process")
For Each objProcess in colProcessList
    Wscript.Echo "Process: " & objProcess.Name 
    Wscript.Echo "Process ID: " & objProcess.ProcessID 
    Wscript.Echo "Thread Count: " & objProcess.ThreadCount 
    Wscript.Echo "Page File Size: " _
        & objProcess.PageFileUsage 
    Wscript.Echo "Page Faults: " _
        & objProcess.PageFaults 
    Wscript.Echo "Working Set Size: " _
        & objProcess.WorkingSetSize 
Next

It also requires that you write an entire script, and it offers no lightweight interactive experience. The Microsoft Scripting Guys’ Scriptomatic tool helps make it easier to create many of these mundane scripts, but it still doesn’t address one-off queries.

Enter PowerShell.

PowerShell elevates WMI to a first-class citizen for both ad-hoc and structured queries. Since most of the template VBScript for dealing with WMI instances ends up being used to display the results, PowerShell eliminates this step completely. The PowerShell equivalent of the preceding VBScript is simply:

Get-WmiObject Win32_Process -Computer atl-dc-01

Or, if you want a subset of properties:

Get-WmiObject Win32_Process | Select Name,ProcessId,ThreadCount

By providing a deep and user-friendly integration with WMI, PowerShell puts a great deal of functionality at the fingertips of every administrator.

Access Windows Management Instrumentation Data

Problem

You want to work with data and functionality provided by the WMI facilities in Windows.

Solution

To retrieve all instances of a WMI class, use the Get-WmiObject cmdlet:

Get-WmiObject -ComputerName Computer -Class Win32_Bios

To retrieve specific instances of a WMI class using a WMI filter, supply an argument to the -Filter parameter of the Get-WmiObject cmdlet. This is the WHERE clause of a WQL statement, but without the WHERE keyword:

Get-WmiObject Win32_Service -Filter "StartMode = 'Auto'"

To retrieve instances of a WMI class using WMI’s WQL language, use the [WmiSearcher] type shortcut:

$query = [WmiSearcher] "SELECT * FROM Win32_Service WHERE StartMode = 'Auto'"
$query.Get()

To retrieve a specific instance of a WMI class using a WMI filter, use the [Wmi] type shortcut:

[Wmi] 'Win32_Service.Name="winmgmt"'

To retrieve a property of a WMI instance, access that property as you would access a .NET property:

$service = [Wmi] 'Win32_Service.Name="winmgmt"'
$service.StartMode

To invoke a method on a WMI instance, invoke that method as you would invoke a .NET method:

$service = [Wmi] 'Win32_Service.Name="winmgmt"'
$service.ChangeStartMode("Manual")
$service.ChangeStartMode("Automatic")

To invoke a method on a WMI class, use the Invoke-WmiMethod cmdlet. Alternatively, use the [WmiClass] type shortcut to access that WMI class. Then, invoke that method as you would invoke a .NET method:

Invoke-WmiMethod Win32_Process Create notepad

$class = [WmiClass] "Win32_Process"
$class.Create("Notepad")

To retrieve a WMI class from a specific namespace, use its fully qualified name along with the [WmiClass] type shortcut:

[WmiClass] "\COMPUTERRootCimv2:Win32_Process"

Discussion

Working with WMI has long been a staple of managing Windows systems—especially systems that are part of corporate domains or enterprises. WMI supports a huge number of Windows management tasks, albeit not in a very user-friendly way.

Traditionally, administrators required either VBScript or the WMIC command-line tool to access and manage these systems through WMI. While powerful and useful, these techniques still provided plenty of opportunities for improvement. VBScript lacks support for an ad-hoc investigative approach, and WMIC fails to provide (or take advantage of) knowledge that applies to anything outside WMIC.

In comparison, PowerShell lets you work with WMI just like you work with the rest of the shell. WMI instances provide methods and properties, and you work with them the same way you work with methods and properties of other objects in PowerShell.

Not only does PowerShell make working with WMI instances and classes easy once you have them, but it also provides a clean way to access them in the first place. For most tasks, you need only to use the simple [Wmi], [WmiClass], or [WmiSearcher] syntax as shown in the solution.

Along with WMI’s huge scope, though, comes a related problem: finding the WMI class that accomplishes your task. To assist you in learning what WMI classes are available, Appendix G provides a helpful listing of the most common ones. For a script that helps you search for WMI classes by name, description, property name, or property description, see Program: Search for WMI Classes.

Some advanced WMI tasks require that you enable your security privileges or adjust the packet privacy settings used in your request. All of PowerShell’s WMI cmdlets support these options through built-in parameters.

When you want to access a specific WMI instance with the [Wmi] accelerator, you might at first struggle to determine what properties WMI lets you search on. These properties are called key properties on the class. For a script that lists these key properties, see Program: Determine Properties Available to WMI Filters.

For more information about the Get-WmiObject cmdlet, type Get-Help Get-WmiObject.

Modify the Properties of a WMI Instance

Problem

You want to modify the properties of a WMI instance.

Solution

Use the Set-WmiInstance cmdlet:

PS > $bootVolume = Get-WmiObject Win32_LogicalDisk |
    Where-Object { $_.DeviceID -eq 'C:' }

PS > $bootVolume

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 10587656192
Size         : 34357637120
VolumeName   : Boot Volume

PS > $bootVolume | Set-WmiInstance -Arguments @{ VolumeName = 'Vista' }

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 10587656192
Size         : 34357637120
VolumeName   : Vista

Discussion

Although you can assign new property values to the objects output by Get-WmiObject, changes you make ultimately are not reflected in the permanent system state, as this example shows:

PS > $bootVolume = Get-WmiObject Win32_LogicalDisk |
    Where-Object { $_.DeviceID -eq 'C:' }

PS > $bootVolume

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 10587656192
Size         : 34357637120
VolumeName   : Vista

PS > $bootVolume.VolumeName = "Boot Volume"

PS > Get-WmiObject Win32_LogicalDisk |
    Where-Object { $_.DeviceID -eq 'C:' }


DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 10587652096
Size         : 34357637120
VolumeName   : Vista

Instead, the Set-WmiInstance cmdlet lets you permanently modify values of WMI instances. While the Set-WmiInstance cmdlet supports WMI instances as pipeline input, you can also pass the fully qualified path to the -Path parameter:

Set-WmiInstance -Path "Win32_LogicalDisk.DeviceID='C:'" `
    -Argument @{ VolumeName="Vista" }

To determine which properties can be modified on an instance, you need to investigate the WMI class that defines it. Each WMI class has a Properties collection, and each property has a Qualifiers collection. If Write is one of the qualifiers, then that property is writeable:

PS > [WmiClass] "Win32_LogicalDisk" | Select -Expand Properties

(...)
Name       : VolumeName
Value      :
Type       : String
IsLocal    : True
IsArray    : False
Origin     : Win32_LogicalDisk
Qualifiers : {CIMTYPE, MappingStrings, read, write}

Name       : VolumeSerialNumber
Value      :
Type       : String
IsLocal    : True
IsArray    : False
Origin     : Win32_LogicalDisk
Qualifiers : {CIMTYPE, MappingStrings, read}
(...)

To automatically see all writeable classes in the ROOTCIMV2 namespace, simply run this snippet of PowerShell script:

$writeableProperties = Get-WmiObject -List -Recurse |
    Select -Expand Properties |
    Where-Object { $_ | Select -Expand Qualifiers |
        Where-Object { $_.Name -eq "Write" } } | Select Origin,Name

Like all other WMI-related cmdlets, the Set-WmiInstance cmdlet lets you configure impersonation, authentication, and privilege restrictions. For more information about working with WMI classes, see Access Windows Management Instrumentation Data.

Invoke a Method on a WMI Class

Problem

You want to invoke a method supported by a WMI class.

Solution

Use the Invoke-WmiMethod cmdlet:

PS > Invoke-WmiMethod -Class Win32_Process -Name Create -Args notepad.exe
(notepad starts)

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ProcessId        : 3644
ReturnValue      : 0

Discussion

As with .NET types, WMI classes describe the functionality and features of a related set of items. For example, the Win32_Process class describes the features and behavior of an entity called an operating system process. When WMI returns information about a specific operating system process, that is called an instance.

As with static methods on .NET types, many WMI classes offer methods that relate broadly to the entity they try to represent. For example, the Win32_Process class defines methods to start processes, stop them, and more. To invoke any of these methods, call the Invoke-WmiMethod cmdlet.

While you may already know the method you want to call, PowerShell also offers a way to see the methods exposed by WMI classes on your system. Each WMI class has a Methods collection, and reviewing that collection lists all methods supported by that class. The following snippet lists all methods supported by all classes in the ROOTCIMV2 namespace:

Get-WmiObject -List -Recurse | Select -Expand Methods | Select Origin,Name

Like all other WMI-related cmdlets, the Invoke-WmiMethod cmdlet lets you configure impersonation, authentication, and privilege restrictions.

In addition to the Invoke-WmiMethod cmdlet, the [WmiClass] type shortcut also lets you refer to a WMI class and invoke its methods:

$processClass = [WmiClass] "Win32_Process"
$processClass.Create("notepad.exe")

This method, however, does not easily support customization of impersonation, authentication, or privilege restrictions.

For more information about working with WMI classes, see Access Windows Management Instrumentation Data.

Program: Determine Properties Available to WMI Filters

When you want to access a specific WMI instance with PowerShell’s [Wmi] type shortcut, you might at first struggle to determine what properties WMI lets you search on. These properties are called key properties on the class. Example 28-1 gets all the properties you can use in a WMI filter for a given class.

Example 28-1. Get-WmiClassKeyProperty.ps1

##############################################################################
##
## Get-WmiClassKeyProperty
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################

<#

.SYNOPSIS

Get all of the properties that you can use in a WMI filter for a given class.

.EXAMPLE

Get-WmiClassKeyProperty Win32_Process
Handle

#>

param(
    ## The WMI class to examine
    [WmiClass] $WmiClass
)

Set-StrictMode -Version Latest

## WMI classes have properties
foreach($currentProperty in $wmiClass.Properties)
{
    ## WMI properties have qualifiers to explain more about them
    foreach($qualifier in $currentProperty.Qualifiers)
    {
        ## If it has a 'Key' qualifier, then you may use it in a filter
        if($qualifier.Name -eq "Key")
        {
            $currentProperty.Name
        }
    }
}

For more information about running scripts, see Run Programs, Scripts, and Existing Tools.

Program: Search for WMI Classes

Along with WMI’s huge scope comes a related problem: finding the WMI class that accomplishes your task. To help you learn what WMI classes are available, Appendix G provides a helpful listing of the most common ones. If you want to dig a little deeper, though, Example 28-2 lets you search for WMI classes by name, description, property name, or property description.

Example 28-2. Search-WmiNamespace.ps1

##############################################################################
##
## Search-WmiNamespace
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################

<#

.SYNOPSIS

Search the WMI classes installed on the system for the provided match text.

.EXAMPLE

Search-WmiNamespace Registry
Searches WMI for any classes or descriptions that mention "Registry"

.EXAMPLE

Search-WmiNamespace Process ClassName,PropertyName
Searches WMI for any classes or properties that mention "Process"

.EXAMPLE

Search-WmiNamespace CPU -Detailed
Searches WMI for any class names, descriptions, or properties that mention
"CPU"

#>

param(
    ## The pattern to search for
    [Parameter(Mandatory = $true)]
    [string] $Pattern,

    ## Switch parameter to look for class names, descriptions, or properties
    [switch] $Detailed,

    ## Switch parameter to look for class names, descriptions, properties, and
    ## property description.
    [switch] $Full,

    ## Custom match options.
    ## Supports any or all of the following match options:
    ## ClassName, ClassDescription, PropertyName, PropertyDescription
    [string[]] $MatchOptions = ("ClassName","ClassDescription")
)

Set-StrictMode -Off

## Helper function to create a new object that represents
## a Wmi match from this script
function New-WmiMatch
{
    param( $matchType, $className, $propertyName, $line )

    $wmiMatch = New-Object PsObject -Property @{
        MatchType = $matchType;
        ClassName = $className;
        PropertyName = $propertyName;
        Line = $line
    }

    $wmiMatch
}

## If they've specified the -detailed or -full options, update
## the match options to provide them an appropriate amount of detail
if($detailed)
{
    $matchOptions = "ClassName","ClassDescription","PropertyName"
}

if($full)
{
    $matchOptions =
        "ClassName","ClassDescription","PropertyName","PropertyDescription"
}

## Verify that they specified only valid match options
foreach($matchOption in $matchOptions)
{
    $fullMatchOptions =
        "ClassName","ClassDescription","PropertyName","PropertyDescription"

    if($fullMatchOptions -notcontains $matchOption)
    {
        $error = "Cannot convert value {0} to a match option. " +
            "Specify one of the following values and try again. " +
            "The possible values are ""{1}""."
        $ofs = ", "
        throw ($error -f $matchOption, ([string] $fullMatchOptions))
    }
}

## Go through all of the available classes on the computer
foreach($class in Get-WmiObject -List -Rec)
{
    ## Provide explicit get options, so that we get back descriptions
    ## as well
    $managementOptions = New-Object System.Management.ObjectGetOptions
    $managementOptions.UseAmendedQualifiers = $true
    $managementClass =
        New-Object Management.ManagementClass $class.Name,$managementOptions

    ## If they want us to match on class names, check if their text
    ## matches the class name
    if($matchOptions -contains "ClassName")
    {
        if($managementClass.Name -match $pattern)
        {
            New-WmiMatch "ClassName" `
                $managementClass.Name $null $managementClass.__PATH
        }
    }

    ## If they want us to match on class descriptions, check if their text
    ## matches the class description
    if($matchOptions -contains "ClassDescription")
    {
        $description =
            $managementClass.Qualifiers |
                foreach { if($_.Name -eq "Description") { $_.Value } }
        if($description -match $pattern)
        {
            New-WmiMatch "ClassDescription" `
                $managementClass.Name $null $description
        }
    }

    ## Go through the properties of the class
    foreach($property in $managementClass.Properties)
    {
        ## If they want us to match on property names, check if their text
        ## matches the property name
        if($matchOptions -contains "PropertyName")
        {
            if($property.Name -match $pattern)
            {
                New-WmiMatch "PropertyName" `
                    $managementClass.Name $property.Name $property.Name
            }
        }

        ## If they want us to match on property descriptions, check if
        ## their text matches the property name
        if($matchOptions -contains "PropertyDescription")
        {
            $propertyDescription =
                $property.Qualifiers |
                    foreach { if($_.Name -eq "Description") { $_.Value } }
            if($propertyDescription -match $pattern)
            {
                New-WmiMatch "PropertyDescription" `
                    $managementClass.Name $property.Name $propertyDescription
            }
        }
    }
}

For more information about running scripts, see Run Programs, Scripts, and Existing Tools.

Use .NET to Perform Advanced WMI Tasks

Problem

You want to work with advanced features of WMI, but PowerShell’s access (through the [Wmi], [WmiClass], and [WmiSearcher] accelerators) does not directly support them.

Solution

To interact with advanced features of WMI objects, access their methods and properties.

Advanced instance features

To get WMI instances related to a given instance (its associators), call the GetRelated() method:

$instance = [Wmi] 'Win32_Service.Name="winmgmt"'
$instance.GetRelated()

To change advanced scope options, access the Scope.Options property. While the Invoke-WmiMethod cmdlet lets you enable privileges directly through a parameter, this example provides another option:

$system = Get-WmiObject Win32_OperatingSystem
$system.Scope.Options.EnablePrivileges = $true
$system.SetDateTime($class.ConvertFromDateTime("01/01/2007"))

Advanced class features

To retrieve the WMI properties and qualifiers of a class, access the Properties property:

$class = [WmiClass] "Win32_Service"
$class.Properties

Advanced query feature

To configure connection options on a query, such as Packet Privacy and Authentication, set the options on the Scope property:

$credential = Get-Credential
$query = [WmiSearcher] "SELECT * FROM IISWebServerSetting"
$query.Scope.Path = "\REMOTE_COMPUTERRootMicrosoftIISV2"
$query.Scope.Options.Username = $credential.Username
$query.Scope.Options.Password = $credential.GetNetworkCredential().Password
$query.Scope.Options.Authentication = "PacketPrivacy"
$query.get() | Select-Object AnonymousUserName

Discussion

The [Wmi], [WmiClass], and [WmiSearcher] type shortcuts return instances of .NET System.Management.ManagementObject, System.Management.ManagementClass, and System.Management.ManagementObjectSearcher classes, respectively.

As might be expected, the .NET Framework provides comprehensive support for WMI queries, with PowerShell providing an easier-to-use interface to that support. If you need to step outside the support offered directly by PowerShell, these classes in the .NET Framework provide an advanced outlet.

For more information about working with classes from the .NET Framework, see Work with .NET Objects.

Improve the Performance of Large-Scale WMI Operations

Problem

You want to perform a large-scale WMI operation across many computers, and you want to control how many computers should be managed at a time.

Solution

Use the -ThrottleLimit parameter on the cmdlet, and invoke that cmdlet as a job:

$computers = Get-Content computers.txt
Get-WmiObject Win32_OperatingSystem -Computer $computers -ThrottleLimit 10 -AsJob

Discussion

One problem with large-scale WMI operations against many computers is that most scripts invoke them sequentially. If your script acts against 10,000 servers, it will usually process the first computer, and then retrieve the results. Next, it will process the second computer, and then retrieve its results. Since WMI operations are traditionally network-bound, your script spends the vast majority of its time simply waiting for results from remote computers.

Note

A genesis for this feature was a sobering story we heard from one of our large customers. The customer’s scripts had to deal with so many computers that the customer would have to start a second script before the first had finished!

The solution to this quandary comes from invoking the commands in parallel. Not entirely in parallel, however, as most machines would buckle under the load of 10,000 active WMI queries. While it is possible to recognize the solution and pitfalls, actually implementing it is something different altogether. Even with the proper skill set, a job manager that supports automatic throttling is usually not high on an administrator’s list of priorities when compared to the collection of fires the administrator needs to put out.

Instead, PowerShell’s WMI cmdlets handle all of this complexity for you. For more information about PowerShell’s job support, see Invoke a Long-Running or Background Command.

Convert a VBScript WMI Script to PowerShell

Problem

You want to perform a WMI task in PowerShell, but you 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 Get-WmiObject cmdlet:

foreach($printer in Get-WmiObject -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 | Invoke-WmiMethod -Name ChangeStartMode -ArgumentList "Manual"
$service | Invoke-WmiMethod -Name ChangeStartMode -ArgumentList "Automatic"

To accomplish the task of a script that calls methods on a class, use the Invoke-WmiMethod cmdlet, or use the [WmiClass] accelerator to retrieve the class, and then call methods on the class like you would call any other PowerShell method:

Invoke-WmiMethod Win32_Process Create notepad

$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.

Note

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 28-3.

Example 28-3. Retrieving printer information from WMI using VBScript

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\" & strComputer & "
ootcimv2")

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 Get-WmiObject 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 = Get-WmiObject Win32_Printer -ComputerName computer

If you need to specify a different computer, namespace, or query restriction, the Get-WmiObject cmdlets supports those through optional parameters. If you need to specify advanced connection options (such as authentication levels), simply specify those in the -Impersonation and -Authentication parameters to the cmdlet.

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:

Get-WmiObject Win32_Printer -ComputerName computer | Format-List Name,Location,Default

For more information about working with the Get-WmiObject cmdlet, see Access Windows Management Instrumentation Data.

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 28-4 changes the startup type of a service.

Example 28-4. Changing the startup type of a service from WMI using VBScript

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\" & strComputer & "
ootcimv2")

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 Get-WmiObject 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 = Get-WmiObject Win32_Service -Filter "StartMode = 'Manual'"

If you need to specify a different computer or namespace, the Get-WmiObject cmdlet supports those through optional parameters. If you need to specify advanced connection options (such as authentication levels), simply specify those in the -Impersonation and -Authentication parameters to the cmdlet.

In PowerShell, the For Each block becomes:

foreach($service in $services)
{
    $service.ChangeStartMode("Disabled")
}

For more information about working with the Get-WmiObject cmdlet, see Access Windows Management Instrumentation Data.

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 & "
ootcimv2: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 Invoke-WmiMethod cmdlet lets you easily work with methods on a class. The entire segment of code then becomes:

Invoke-WmiMethod "\COMPUTERRootCimv2:Win32_Process" Create notepad.exe

For more information about invoking methods on WMI classes, see Invoke a Method on a WMI Class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.122.244