Read Windows Server 2008 R2 Unleashed Online
Authors: Noel Morimoto
21
PS C:\> get-wmiobject -namespace “root/cimv2” -list | where {$_.Name
-eq “Win32_Product”} | format-list *
Name : Win32_Product
__GENUS : 1
__CLASS : Win32_Product
__SUPERCLASS : CIM_Product
__DYNASTY : CIM_Product
__RELPATH : Win32_Product
__PROPERTY_COUNT : 12
__DERIVATION : {CIM_Product}
__SERVER : PLANX
__NAMESPACE : ROOT\cimv2
__PATH : \\PLANX\ROOT\cimv2:Win32_Product
...
PS C:\>
Although using Get-WmiObject is simple, using it almost always requires typing a long
ptg
command string. This drawback brings you to the third method for using WMI in
PowerShell: the WMI type accelerators.
[WMI] Type Accelerator
This type accelerator for the ManagementObject class takes a WMI object path as a string
and gets a WMI object bound to an instance of the specified WMI class, as shown in
this example:
PS C:\> $CompInfo = [WMI]”root\cimv2:Win32_ComputerSystem.Name=’PLANX’”
PS C:\> $CompInfo
Domain : companyabc.com
Manufacturer : Hewlett-Packard
Model : Pavilion dv8000 (ES184AV)
Name : PLANX
PrimaryOwnerName : Frank Miller
TotalPhysicalMemory : 2145566720
PS C:\>
NOTE
To bind to an instance of a WMI object directly, you must include the key property in the
WMI object path. For the preceding example, the key property is Name.
750
CHAPTER 21
Automating Tasks Using PowerShell Scripting
[WMIClass] Type Accelerator
This type accelerator for the ManagementClass class takes a WMI object path as a string and
gets a WMI object bound to the specified WMI class, as shown in the following example:
PS C:\> $CompClass = [WMICLASS]”\\.\root\cimv2:Win32_ComputerSystem”
PS C:\> $CompClass
NameSpace: ROOT\cimv2
Name Methods Properties
---- ------- ----------
Win32_ComputerSystem {SetPowerState, R... {AdminPasswordSt...
PS C:\> $CompClass | format-list *
Name : Win32_ComputerSystem
__GENUS : 1
__CLASS : Win32_ComputerSystem
__SUPERCLASS : CIM_UnitaryComputerSystem
__DYNASTY : CIM_ManagedSystemElement
__RELPATH : Win32_ComputerSystem
ptg
__PROPERTY_COUNT : 54
__DERIVATION : {CIM_UnitaryComputerSystem, CIM_ComputerSystem, CIM_System,
CIM_LogicalElement...}
__SERVER : PLANX
__NAMESPACE : ROOT\cimv2
__PATH : \\PLANX\ROOT\cimv2:Win32_ComputerSystem
...
PS C:\>
[WMISearcher] Type Accelerator
This type accelerator for the ManagementObjectSearcher class takes a WQL string and creates
a WMI searcher object. After the searcher object is created, you use the Get() method to get
a WMI object bound to an instance of the specified WMI class, as shown here:
PS C:\> $CompInfo = [WMISearcher]”Select * From Win32_ComputerSystem”
PS C:\> $CompInfo.Get()
Domain : companyabc.com
Manufacturer : Hewlett-Packard
Model : Pavilion dv8000 (ES184AV)
Name : PLANX
PrimaryOwnerName : Miro
Using Windows PowerShell
751
TotalPhysicalMemory : 2145566720
21
PS C:\>
AuthenticationLevel
and
ImpersonationLevel
When using the Get-WmiObject cmdlet in PowerShell 1.0 in conjunction with the
IIsWebService class to manage the W3SVC service on a remote machine, the following
error would be encountered:
PS > get-wmiobject -class IIsWebService -namespace “root\microsoftiisv2” -Computer
sc1-app01
Get-WmiObject : Access denied
At line:1 char:14
+ Get-WMIObject <<<< -class IIsWebService -namespace “root\microsoftiisv2” -com-
puter sc1-app01
This is normal behavior for any of the IIS WMI classes because they require the
AuthenticationLevel property defined as PacketPrivacy. The AuthenticationLevel prop-
ptg
erty is an integer, which defines the COM authentication level that is assigned to an
object and in the end determines how DCOM will protect information sent from WMI. In
this case, the IIS WMI classes require that data is encrypted, which is not the default
behavior of WMI.
Although defining the AuthenticationLevel property in WSH was a simple line of code,
in PowerShell 1.0’s version of the Get-WmiObject cmdlet, there was no method to define
this property. Additionally, there wasn’t a way to change either the ImpersonationLevel
property or enable all privileges, both of which are often requirements when working with
WMI. To correct this problem, the product team has updated the Get-WmiObject cmdlet
in PowerShell 2.0 to include new parameters to define the AuthenticationLevel and
ImpersonationLevel properties, as well as enable all privileges. Additionally, these parame-
ters also work with the new WMI cmdlets (Invoke-WMIMethod, Remove-WMIObject, and
Set-WMIInstance), which were also introduced in PowerShell 2.0. For example:
PS > get-wmiobject -class IIsWebService -namespace “root\microsoftiisv2” -Computer
sc1-app01 –Authentication 6
In the previous example, the Authentication parameter is used to define the
AuthenticationLevel property. In this case, the value is defined as 6 (PacketPrivacy).
Set-WMIInstance Cmdlet
The Set-WMIInstance cmdlet was developed to reduce the number of steps needed to
change a read-write WMI property (or property that allows direct modification). For
example, in PowerShell 1.0, the following set of commands might be used to change the
LoggingLevel for the WMI service:
752
CHAPTER 21
Automating Tasks Using PowerShell Scripting
PS C:\> $WMISetting = Get-WMIObject Win32_WMISetting
PS C:\> $WMISetting.LoggingLevel = 2
PS C:\> $WMISetting.Put()
By using the Set-WMIInstance cmdlet, you can complete the same task using a single
command:
PS > set-wmiinstance –class “Win32_WMISetting” –argument @{LoggingLevel=2}
In the previous example, the class parameter is defined as a Win32_WMISetting, whereas
the argument parameter is defined as a HashTable that contains the property and the
value the property will be set to. Additionally, because this parameter requires an argu-
ment that is a HashTable, then to define multiple property and value pairs, you would
separate the pairs with a semicolon, as shown here:
–argument @{LoggingLevel=1;MaxLogFileSize=1000}
However, the true power of this cmdlet is to use the computername parameter to change
read-write WMI properties on multiple machines at once. For example:
PS > set-wmiinstance –class “Win32_WMISetting” –argument @{LoggingLevel=1} –comput-
ername sc1-app01,sc1-app02
ptg
The arguments for the computername parameter can be either a NetBIOS name, fully quali-
fied domain name (FQDN), or IP address. Additionally, each argument must be separated
by a comma.
Invoke-WMIMethod Cmdlet
With WMI, there are two different types of methods: instance or static. With static
methods, you must invoke the method from the class itself, whereas instance methods are
invoked on specific instances of a class. In PowerShell 1.0, working with instance methods
were fairly straightforward and only involved creating an object of a particular instance of
a WMI class. However, to work with a static method required a fairly complex and unintu-
itive WQL statement, as shown in the following example:
PS > $ProcFac = get-wmiobject -query “SELECT * FROM Meta_Class WHERE __Class =
‘Win32_Process’” -namespace “root\cimv2”
PS > $ProcFac.Create(“notepad.exe”)
Granted, you could also use the [WMIClass] type accelerator, as shown here:
PS > $ProcFac = [wmiclass]”Win32_Process”
PS > $ProcFac.Create(“notepad.exe”)
But, if you wanted to use the Get-WMIObject cmdlet or were having problems with the
[WMIClass] type accelerator, employing the use of the noted WQL statement wasn’t very
command-line friendly. To fill this noted gap, the PowerShell product team has introduced
the Invoke-WMIMethod cmdlet in PowerShell 2.0.
Using Windows PowerShell
753
As its name suggests, the purpose of the Invoke-WMIMethod cmdlet is to make it easier to
directly invoke WMI methods. To use this cmdlet to invoke a static method, you use the
21
following command:
PS > invoke-wmimethod -path “Win32_Process” -name “create” -argumentList
“notepad.exe”
In the previous command example, the path parameter requires the name of the WMI
class from which the method is to be invoked. In this case, the method being invoked is
the Create method as defined for the name parameter. If you were invoking an instance
method, the argument for the path parameter would need to be the complete path to an
existing WMI instance. For example:
PS > invoke-wmimethod -path “Win32_Process.Handle=’42144’” -name terminate
Finally, the argumentList parameter is used to define any arguments that a method
requires when it is invoked. In cases where the method requires multiple values or you
want to pass multiple values, you must assign those values into an array. Then, the array
must be defined as the argument for the argumentList parameter.
NOTE
ptg
Values for methods are not in the same order as used with the WMI’s scripting API.
Instead, values are ordered such as they appear in Wbemtest.exe.
Remove-WMIObject Cmdlet
The last new cmdlet to be introduced in PowerShell 2.0 is the Remove-WMIObject cmdlet.
This cmdlet is used to remove instances of WMI objects. For example, to terminate a
process using WMI in PowerShell 1.0, you might use the following set of commands:
PS > $Proc = get-wmiobject -class “Win32_Process” -filter “Name=’wordpad.exe’”
PS > $Proc.Terminate()
However, depending on the type of WMI object that you are trying to remove, there can
be any number of methods that would need to be used. For instance, to delete a folder
using WMI in PowerShell 1.0, you would use the following command:
PS > $Folder = get-wmiobject -query “Select * From Win32_Directory Where Name
=’C:\\Scripts’”
PS > $Folder.Delete()
Conversely, using the Remove-WMIObject cmdlet, you can remove instances of any type
of WMI object. For example, to remove an instance of the Win32_Process class, you would
use the following commands:
PS > $Proc = get-wmiobject -class “Win32_Process” -filter “Name=’wordpad.exe’”
754
CHAPTER 21
Automating Tasks Using PowerShell Scripting
PS > $Proc | remove-wmiobject
Whereas the following commands are used to remove a directory:
PS > $Folder = get-wmiobject -query “Select * From Win32_Directory Where Name
=’C:\\Scripts’”
PS > $Folder | remove-wmiobject
Using Snap-Ins
Snap-ins are used to show a list of all the registered PSSnapins outside of the default snap-
ins that come with PowerShell. Entering the command Get-PSSnapin -Registered on a
newly installed PowerShell system will return nothing, as shown in the following example:
PS C:\> get-pssnapin -registered
In most cases, a setup program will accompany a PowerShell snap-in and ensure that it
becomes correctly registered for use. However, if this is not the case, the .NET utility
InstallUtil.exe is used to complete the registration process. In the following example,
InstallUtil.exe is being used to install a third-party library file called freshtastic-
automation.dll:
ptg
PS C:\> & “$env:windir\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe” fresh-
tastic-automation.dll
Once the DLL library file has been registered with PowerShell, the next step is to register
the DLL’s snap-in with PowerShell so that the cmdlets contained in the DLL are made
available to PowerShell. In the case of the freshtastic-automation library, the snap-in is
registered by using the command Add-PSSnapin freshtastic, as follows:
PS C:\> add-pssnapin freshtastic
Now that the freshtastic snap-in has been registered, you can enter the following command
Get-Help freshtastic to review the usage information for the freshtastic cmdlets:
PS C:\> get-help freshtastic
Now that the registration of the freshtastic library DLL is complete and the associated
snap-in has been added to the console, you can enter the command Get-PSSnapin
–registered again and see that the freshtastic snap-in has been added to the console:
PS C:\> get-pssnapin -registered
Name : freshtastic
PSVersion : 2.0
Using Windows PowerShell
755
Description : Used to automate freshness.
21
PS C:\>
Now that you have registered the third-party library file and added its snap-in to the
console, you might find that the library does not meet your needs, and you want to
remove it. The removal process is basically a reversal of the installation steps listed previ-
ously. First, you remove the snap-in from the console using the command Remove-