Managing Processes
In PowerShell, you can use two
cmdlets to manage processes. The first cmdlet, Get-Process, is used to
get information about the current processes that are running on the
local Windows system:
PS C:\> get-process
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
782 12 2500 4456 113 4.02 448 csrss
237 10 3064 6228 113 76.70 488 csrss
292 26 20180 14632 356 12.94 1496 dfsrs
160 13 3020 5536 55 0.34 2696 dfssvc
203 24 6368 5888 64 1.75 3220 dns
...
To filter the object
collection that is returned by the Get-Process cmdlet to a particular
process, you can specify the process name or ID, as shown in the
following example:
PS C:\> get-process dns
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
203 24 6368 5888 64 1.77 3220 dns
PS C:\> get-process -id 3220
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
203 24 6368 5888 64 1.77 3220 dns
PS C:\>
In addition to the preceding examples, you could also combine the Get-Process cmdlet with the Where-Object cmdlet. For example:
PS C:\> get-process | ? {$_.workingset -gt 100000000} | sort ws -descending
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
471 29 108608 104972 658 95.88 4208 mmc
629 39 130716 104208 705 108.58 4332 mmc
PS C:\>
By using these cmdlets together,
a more robust view of the current running processes based on a
specified filter statement can be created. In the previous example, the
resulting object collection includes processes that only have a working
set greater than 100,000,000 bytes. In addition, the Sort-Object cmdlet
is used to sort the formatted table’s WS(K) column in descending order.
The second cmdlet that is used to manage processes is the Stop-Process cmdlet. Usage of this cmdlet is as follows:
PS C:\work\logs> stop-process -name notepad
The process that is being
stopped can either be defined by its name, ID, or as an object that is
passed to the Stop-Process cmdlet via the pipeline.
Using WMI
Using WMI in PowerShell has
similar conceptual logic as in WSH. The main difference is that the
PowerShell methods are based on WMI .NET instead of the WMI Scripting
API. You have three methods for using WMI in PowerShell: WMI .NET (which
is the .NET System.Management and System.Management.Instrumentation namespaces), the Get-WmiObject cmdlet, or the PowerShell WMI type accelerators: [WMI], [WMIClass], and [WMISearcher].
The first method, using the System.Management and System.Management.Instrumentation
namespaces. It should be only a fallback method in
case PowerShell isn’t correctly encapsulating an object within a PSObject object when using the other two methods.
The
second method, the Get-WmiObject cmdlet, retrieves WMI objects and
gathers information about WMI classes. This cmdlet is fairly simple. For
example, getting an instance of the local Win32_ComputerSystem class just requires the name of the class, as shown here:
PS C:\> get-wmiobject "Win32_ComputerSystem"
Domain : companyabc.com
Manufacturer : Hewlett-Packard
Model : Pavilion dv8000 (ES184AV)
Name : Wii
PrimaryOwnerName : Damon Cortesi
TotalPhysicalMemory : 2145566720
PS C:\>
The next example, which is more robust, connects to the remote machine named Jupiter and gets an instance of the Win32_Service
class in which the instance’s name equals Virtual Server. The result is
an object containing information about the Virtual Server service on
Jupiter:
PS C:\> get-wmiobject -class "Win32_Service" -computerName "Jupiter" -filter
"Name='Virtual Server'"
ExitCode : 0
Name : Virtual Server
ProcessId : 656
StartMode : Auto
State : Running
Status : OK
PS C:\>
The following command returns the same information as the previous one but makes use of a WQL query:
PS C:\> get-wmiobject -computerName "Jupiter" -query "Select *From Win32_Service
Where Name='Virtual Server'"
ExitCode : 0
Name : Virtual Server
ProcessId : 656
StartMode : Auto
State : Running
Status : OK
PS C:\>
Finally, here’s an example of using Get-WmiObject to gather information about a WMI class:
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 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.
[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
__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
TotalPhysicalMemory : 2145566720
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
property 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
parameters 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:
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 argument 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
The arguments for the computername
parameter can be either a NetBIOS name, fully qualified 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
unintuitive 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.
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 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
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'"
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