Managing Windows Services with PowerShell. Part 4. Modifying Services Using WMI
- Transfer
- Tutorial

We continue to publish translations of Windows service management articles available on 4sysops.com . In a previous post , we looked at using WMI to retrieve information about a service. The WMI service object offers new properties that are not present in the .NET service object. And although we can use Set-Service to change the service object, there are situations when you need to use WMI.
Under the cut is the translation of the article from the 4sysops.com portal Managing Services the PowerShell way - Part 6 .
Previous articles:
Managing Windows Services with PowerShell. Part 1. Getting the status of services
Managing Windows Services with PowerShell. Part 2. Stop, start, pause We
control Windows services using PowerShell. Part 3. Configuring services using WMI and CIM
Start and stop
As you know, there are no management cmdlets that focus on using WMI, so we must use the methods of the service object.
PS C:\> get-wmiobject win32_service -filter "name='lanmanserver'" | get-member -MemberType Method | Select name
Name
—-
Change
ChangeStartMode
Delete
GetSecurityDescriptor
InterrogateService
PauseService
ResumeService
SetSecurityDescriptor
StartService
StopService
UserControlService
We can also get a reference to a specific service object and then directly invoke a method (directly invoke a method).
PS C:\> $service = get-wmiobject win32_service -filter "name='spooler'"
PS C:\> $service.state
Running
PS C:\> $service.StopService()
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0
I directly call the StopService () method on the Spooler service object. A returned value (“0”) means success. Any other value means an error; see the MSDN documentation for the Win32_Service class.
The disadvantage of this method is that it does not have the –Whatif parameter . Therefore, I recommend using the Invoke-WmiMethod cmdlet . We get the WMI object and pass it to Invoke-WmiMethod .
PS C:\> get-wmiobject win32_service -filter "name='spooler'" | Invoke-WmiMethod
-Name StartService -WhatIf
What if: Performing operation "Invoke-WmiMethod" on Target "Win32_Service
(StartService)".
PS C:\> get-wmiobject win32_service -filter "name='spooler'" | Invoke-WmiMethod
-Name StartService
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0
In a previous article, I looked for those services for which autorun was set, but which for some reason were not started. Now I can slightly change this expression and start the service.
PS C:\> get-wmiobject win32_service -filter "startmode='auto' AND state<>'Running'" -comp chi-dc03 | invoke-wmimethod -Name StartService
The disadvantage of this is that the result object only shows the returned value. If there are no multiple services here, I cannot find out what the result of a particular service is. To solve this problem, we use this option:
PS C:\> get-wmiobject win32_service -filter "startmode='auto' AND state<>'Running'"
-comp chi-dc01,chi-dc02,chi-dc03 | foreach { $svc = $_ ; $_ | Invoke-WmiMethod -Name
StartService | Select @{Name="Name";Expression={$svc.name}},@{Name="DisplayName";
Expression={$svc.Displayname}},ReturnValue,@{Name="Computername";Expression={
$svc.Systemname}}}
Name DisplayName ReturnValue Computername
---- ----------- ----------- ------------
sppsvc Software Protection 0 CHI-DC01
sppsvc Software Protection 0 CHI-DC02
VMTools VMware Tools Service 7 CHI-DC02
ShellHWDetection Shell Hardware Detection 0 CHI-DC03
To the ForEach block, I saved the input object as a variable ( $ svc ), so that I can use it again as part of a hash table that defines custom properties. As you can see, there is one error for the service that I thought I deleted.
Change the startup mode
You can also change the startup mode of the service. Options are: Automatic , Disabled or Manual . Using WMI, you cannot set Automatic (Delayed) service startup values .
PS C:\> get-wmiobject win32_service -filter "name='spooler'" | Invoke-WmiMethod -Name
ChangeStartMode -ArgumentList "Manual" | Select ReturnValue
ReturnValue
-----------
0
The ArgumentList parameter indicates which value should be used. The command is launched with administrator rights.
Set service properties
A service object does not have many properties that you can change. Some WMI objects can be modified using Set-WmiInstance . But in the case of service objects, for the object you need to use the Change () method . The only problem is that this method has many parameters.
Change (
string DisplayName,
string PathName,
uint32 ServiceType,
uint32 ErrorControl,
string StartMode,
boolean DesktopInteract,
string StartName,
string StartPassword,
string LoadOrderGroup,
string LoadOrderGroupDependencies,
string ServiceDependencies
)
You must include these parameters in the method before the one you want to use last. Use the $ Null value for the parameters you want to skip. For example: let's say I want to change the ErrorControl property of the Spooler service from Normal to Ignore. Examining the property of the class , I find that Normal corresponds to the value 1, and Ignore 0. Now let's work with PowerShell.
PS C:\> Get-WmiObject win32_service -filter "Name='Spooler'" | Invoke-WmiMethod
-Name Change -ArgumentList @($null,$null,$null,0) | Select ReturnValue
ReturnValue
-----------
0
It looks like everything is working, check it out.
PS C:\> get-wmiobject win32_service -filter "Name='spooler'" | select
name,errorcontrol
name errorcontrol
---- ------------
Spooler Normal
But no! It turns out that PowerShell has a little “quirk” you should be aware of. Even though the WMI method expects parameters in the given order, ErrorControl should be in fourth place when using Invoke-WmiMethod , alphabetically. And don't ask why. Here is what I do to determine the “correct” order.
PS C:\> $svc = Get-WmiObject win32_service -filter "name='spooler'"
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 11
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
DesktopInteract :
DisplayName :
ErrorControl :
LoadOrderGroup :
LoadOrderGroupDependencies :
PathName :
ServiceDependencies :
ServiceType :
StartMode :
StartName :
StartPassword :
PSComputerName :
In this list, ErrorControl is in 3rd place, so that I can re-run the modified Invoke-WmiMethod expression .
PS C:\> Get-WmiObject win32_service -filter "Name='Spooler'" | Invoke-WmiMethod -Name Change -ArgumentList @($null,$null,0)
Check again and get the desired result.
PS C:\> get-wmiobject win32_service -filter "Name='spooler'" | select
name,errorcontrol
name errorcontrol
---- ------------
Spooler Ignore
Remember that $ null must be included in the argument list for the properties you want to skip. In the next article, we will focus on working with service accounts, as you will probably be working with them using PowerShell.
Total
Using WMI to manage services in your environment is pretty useful, especially for situations where the only option is WMI. But if you are working with PowerShell 3.0, you can also use the CIM cmdlets, which I will discuss in the next article.
Previous articles:
Managing Windows Services with PowerShell. Part 1. Obtaining the status of services We
manage Windows services using PowerShell. Part 2. Stop, start, pause We
control Windows services using PowerShell. Part 3. Configuring services using WMI and CIM