In the last article, we looked at using WMI to manage services with PowerShell. If you are running PowerShell 3.0 you could also use the new CIM cmdlets. The advantage is that these cmdlets use PowerShell remoting to access WMI information, which makes them much more firewall friendly. Here’s how to handle some common service-related tasks with the CIM cmdlets.

Stopping and Starting with CIM cmdlets

One important distinction with a CIM-derived object compared to “pure” WMI, is that the resultant object has no methods. This means you cannot directly invoke a method like StopService(). Instead, you have to use Invoke-CimMethod. Here’s the spooler service on the local computer.

PS C:\> get-ciminstance win32_service -filter "Name='spooler'"

ProcessId        Name           StartMode       State          Status     ExitCode
---------        ----           ---------       -----          ------     --------
0                Spooler        Manual          Stopped        OK         1077

As with WMI, I find the easiest approach is to pipe the object to the Invoke-CimMethod cmdlet.

PS C:\> get-ciminstance win32_service -filter "Name='spooler'" | Invoke-CimMethod 
-Name StartService

                                      ReturnValue PSComputerName
                                      ----------- --------------
                                             0

The cmdlet works pretty much the same way as Invoke-WmiMethod. A return value of 0 indicates success. Let’s revisit an earlier query to find all services that are set to autostart but are not running and then start them.

PS C:\> get-ciminstance win32_service -filter "startmode='auto' and state<>'running'" -computer $computers | Invoke-CimMethod -Name StartService –WhatIf

The $computers variable is an array of computernames. Using Whatif indicates what the command would do if I had allowed it as you can see in the screenshot.

get-ciminstance win32_service

To effect the change I can re-run the command without –WhatIf.

PS C:\> get-ciminstance win32_service -filter "startmode='auto' and state<>'running'" -computer $computers | Invoke-CimMethod -Name StartService

As you can see in the next screenshot I can see where I was successful, although I can’t tell which service was changed.

get-ciminstance win32_service WhatIf

Let’s turn to a variation of something I did in a previous article using Invoke-WmiMethod. In this case, because I’m running PowerShell 3.0, I can take each service object, start it and create a custom object to display the results.

get-ciminstance win32_service -filter "startmode='auto' and state<>'running'" 
-computer $computers | 
foreach {
$result = $_ | Invoke-CimMethod -Name StartService
#create a custom object
[pscustomobject]@{
  Result=$Result.ReturnValue
  Name=$_.Name
  DisplayName=$_.Displayname
  Computername=$Result.PSComputername
 }
} | Sort Computername,Name

Don’t you think the screenshot below is easier to understand?

get-ciminstance win32_service custom object

Of course you can add any other information you need such as the date and time. Or filter this further to only display errors. All I need to do is take my previous expression and filter on the result value.

... | Sort Computername,Name | Where {$_.result -gt 0}
Result                Name               DisplayName            Computername
------                ----               -----------            ------------
7                     VMTools            VMware Tools Service   chi-dc02
2                     gpsvc              Group Policy Client    chi-win8-01

Changing the StartMode

Changing a service property such as the Startmode is equally easy. I don’t need the Remote Access Connection Manager service running on my network, so I’m going to disable it where ever it is found.

PS C:\> get-ciminstance win32_service -filter "name='rasman'" -comp $computers | 
Invoke-CimMethod -methodname ChangeStartmode -Arguments @{startmode='Disabled'}

                                      ReturnValue PSComputerName
                                      ----------- --------------
                                                0 chi-win8-01
                                                0 chi-dc03
                                                0 chi-db01
                                                0 chi-ex01

One slight difference here compared to Invoke-WmiMethod is that the list of arguments must be presented as a dictionary object. The tricky part is identifying the key, which in this case is StartMode. The best thing to do is look at documentation for the WMI method and look at the name of the parameter. Astute readers may also notice that I used –MethodName whereas earlier I used –Name. From what I can gather –Name is an undocumented alias to the –MethodName parameter.

Because we use a dictionary object for method parameters, it is easier to invoke the service object’s Change method. In a previous article I set the ErrorControl property of the Spooler service to Ignore. Let’s set it back to Normal using the CIM cmdlets.

PS C:\> get-ciminstance win32_service -filter "name='spooler'" | Invoke-CimMethod 
-MethodName Change -Arguments @{ErrorControl=1}

                                      ReturnValue PSComputerName
                                      ----------- --------------
                                                0

This is so much easier. No more trying to figure out the position and adding $Null values. Set the specific method parameter and be done with it!

Summary

Using the CIM cmdlets can make remote management very easy and firewall friendly. Yes, it does require PowerShell 3.0 but hopefully you are headed in that direction anyway. Any service management that you could have done with WMI you can also do with the CIM cmdlets, and sometimes with less effort.

I have also stumbled upon another quirk with the CIM cmdlets. Under normal conditions the remote computer must also be running PowerShell 3.0. This holds true when querying all instances of a given class. But when you use a filter, as I’ve done often in this article, then I can query using Get-CimInstance even if the remote computer is running PowerShell 2.0! I’m still investigating why this seems to be happening. But in any case you should be testing everything I demonstrated in this series in a non-production environment any way.

Next up we’ll look specifically at managing the credentials a service is running under.

avatar
1 Comment
  1. Has been useful for me today. Thanks!

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account