📜 ⬆️ ⬇️

Manage Windows services using PowerShell. Part 4. Changing services using WMI


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 services
Manage Windows services using PowerShell. Part 2. Stop, start, pause.
Manage Windows services using PowerShell. Part 3. Configuring Services with WMI and CIM


Start 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 services
Manage Windows services using PowerShell. Part 2. Stop, start, pause.
Manage Windows services using PowerShell. Part 3. Configuring Services with WMI and CIM

Source: https://habr.com/ru/post/168773/


All Articles