
We continue to publish translations of articles on the management of Windows services that go to
4sysops.com . In a
previous post , we considered using WMI to retrieve information about a service. The WMI service object offers new properties that are missing from the .NET service object. And although we can use
Set-Service to modify a service object, there are situations where you need to use WMI.
Under the cut is a translation of an article from the portal 4sysops.com
Managing Services the PowerShell way - Part 6 .
Previous articles:Manage Windows services using PowerShell. Part 1. Get the status of servicesManage Windows services using PowerShell. Part 2. Stop, start, pause.Manage Windows services using PowerShell. Part 3. Configuring Services with WMI and CIMStart and stop
As you know, there are no management cmdlets that would be focused on using WMI, so we need to 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.
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 for the
Spooler service object. Return value (“0”) means success. Any other value means an error; see the MSDN documentation on the Win32_Service class.
The disadvantage of this method is that it lacks the
–Whatif parameter. Therefore, I recommend using the
Invoke-WmiMethod cmdlet . We get a 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 the previous article, I searched 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 is for a particular service. To solve this problem, use the following 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 I can use it again as part of the hash table defining 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 service startup mode. The options are:
Automatic ,
Disabled or
Manual . Using WMI, you cannot set the startup values ​​of the
Automatic (Delayed) service .
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 to use. Run the command as an administrator.
Set service properties
The 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
Spooler ErrorControl property from Normal to Ignore.
Examining the class property , I find that
Normal corresponds to a value of 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 it works, check it out.
PS C:\> get-wmiobject win32_service -filter "Name='spooler'" | select name,errorcontrol name errorcontrol ---- ------------ Spooler Normal
But no! It turned out that PowerShell has a small “fad” that you should be aware of. Even though the WMI method expects parameters in the specified order,
ErrorControl should be in fourth place when using
Invoke-WmiMethod , alphabetically. And do not ask why. This 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 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 the list of arguments must include
$ null for the properties you want to skip. In the next article we will focus on working with service accounts, as you will probably work with them using PowerShell.
Total
Using WMI to manage services in your environment is quite useful, especially for situations where the only option is WMI. But if you are working with PowerShell 3.0, you can also use CIM cmdlets, which I will discuss in the next article.
Previous articles:Manage Windows services using PowerShell. Part 1. Get the status of servicesManage Windows services using PowerShell. Part 2. Stop, start, pause.Manage Windows services using PowerShell. Part 3. Configuring Services with WMI and CIM