I hope this tip will save someone some time as I has spent a good deal of time trying to get this to work they way I wanted. Online findings were only partial solutions to my problem.
Recently, situations cropped up where certain Windows Services were getting stuck in a “StopPending” state and would not resolve no matter how much time was given.
About a year ago I needed a way to monitor windows services in case they went down and send out email notifications so, I wrote it.
I had a UI with a SQL Server back end that would allow me to control turning off and on windows services. I also wrote a monitoring service that ran on a server that would read the table and change the flags and actually do the work of turning off an on the services based on the flags. During that project I also needed the ability to change the StartupType of the service. I wanted it to be set as Manual when it was off and Auto when it was Running.
I found a DLL on Code Project for controlling the StartupType it was simply called ServiceControllerEx.
However, it did not work for a remote computer (another computer on the LAN not on the Internet). I was able to modify the code to connect to remote computers this way:
“\\\\” + this.MachineName + “\\root\\cimv2:Win32_Service.Name='” + this.ServiceName + “‘”
After that it worked great on a remote and the local servers just fine.
Now, back to the “StopPending” problems.
I needed my monitor in some situations to not only try to stop the service but stop any processes owned by the service.
I quickly found out that using Process.Kill() only works on the local machine. If you try to use this on a remote machine it says “Feature is not supported for remote machines.” Researching that message brought me to this blog but did not fully cover the situation I was experiencing. While this would remotely kill the processes on a remote computer it did not cover how to limit it to only processes owned by a specific service.
Note: You also needed to use this method because it allowed you to use a Service Account with the appropriate permissions to control the processes on a remote machine.
I was finally able to solve this my adding a new method to the ServiceControllerEx class that would kill a services processes like this:
Essentially, you can use ManagementObjectSearcher to do it all.
First, define the scope which is the machine name and the service account credentials.
Second, select the ProcessID of the service.
Third, iterate through all the processes on that machine and compare the ParentProcessID to the ProcessID and call the kill command if they match.