I am trying to write a method that shuts down a service on a remote system by process ID if it cannot stop using the StopService method. I tried two different ways to call the "Terminate" method in ManagementObject, and I get two different errors. It is also important to me that I can get the return code from the Terminate method.
If I declare ManagementPath directly to the process that I want to end, I get the error "System.Management.ManagementException: Invalid object path" in the line:
ManagementBaseObject processParams = processObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);
If I get a ManagementObjectCollection and go through it, looking for the identifier of the process I want to complete, I get an "Invalid parameter" error message in the line:
ManagementBaseObject termParams = currentObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);
So, in both cases, I get an error when I try to call the Terminate method, but the error differs depending on how I get to the object (direct path or loop through the collection).
I do not think that this is due to SeDebugPrivilege, since I believe that if it were, I would receive a “denial of access” or “insufficient privilege”.
Code, if I try to directly specify the path to the process:
public int KillServiceWMI(string serviceName, string serverName, string serverUser, string serverDomain, string serverPassword) { try { ConnectionOptions options = new ConnectionOptions(); options.Impersonation = System.Management.ImpersonationLevel.Impersonate; options.Username = serverDomain + "\\" + serverUser; options.Password = serverPassword; ManagementScope scope = new ManagementScope("\\\\" + serverName + "\\root\\cimv2", options); Console.WriteLine("Connecting to scope"); scope.Connect(); Console.WriteLine("Getting ManagementPath"); ManagementPath servicePath = new ManagementPath("Win32_Service.Name='" + serviceName + "'"); Console.WriteLine("Getting ManagementObject"); ManagementObject serviceObj = new ManagementObject(scope, servicePath, new ObjectGetOptions()); Console.WriteLine("Name of service is " + serviceObj["DisplayName"].ToString()); Console.WriteLine("Process ID of service is " + serviceObj["ProcessId"].ToString()); ManagementPath processPath = new ManagementPath("Win32_Process.ProcessId='" + serviceObj["ProcessId"] + "'"); ManagementObject processObj = new ManagementObject(scope, processPath, new ObjectGetOptions()); ManagementBaseObject processParams = processObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null); int returnCode = System.Convert.ToInt32(processParams.Properties["ReturnValue"].Value); return returnCode; } catch (Exception connectEx) { Console.WriteLine("Connecting to " + serverName + " caused an exception"); Console.Write(connectEx); return 99; } }
Code if I am browsing a collection of processes:
public int KillServiceWMI(string serviceName, string serverName, string serverUser, string serverDomain, string serverPassword) { try { ConnectionOptions options = new ConnectionOptions(); options.Impersonation = System.Management.ImpersonationLevel.Impersonate; options.Username = serverDomain + "\\" + serverUser; options.Password = serverPassword; ManagementScope scope = new ManagementScope("\\\\" + serverName + "\\root\\cimv2", options); Console.WriteLine("Connecting to scope"); scope.Connect(); Console.WriteLine("Getting ManagementPath"); ManagementPath servicePath = new ManagementPath("Win32_Service.Name='" + serviceName + "'"); Console.WriteLine("Getting ManagementObject"); ManagementObject serviceObj = new ManagementObject(scope, servicePath, new ObjectGetOptions()); Console.WriteLine("Name of service is " + serviceObj["DisplayName"].ToString()); Console.WriteLine("Process ID of service is " + serviceObj["ProcessId"].ToString()); ObjectQuery serviceQuery = new ObjectQuery("SELECT * from Win32_Process WHERE ProcessID = '" + serviceObj["ProcessId"].ToString() + "'"); ManagementObjectSearcher serviceSearcher = new ManagementObjectSearcher(scope, serviceQuery); ManagementObjectCollection serviceColl = serviceSearcher.Get(); int returnCode = 0; foreach (ManagementObject currentObj in serviceColl) { if (currentObj["ProcessId"].ToString().Equals(serviceObj["ProcessId"].ToString(), StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("Found process " + currentObj["ProcessId"].ToString() + ". Terminating..."); ManagementBaseObject termParams = currentObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null); returnCode = System.Convert.ToInt32(termParams.Properties["ReturnValue"].Value); } } return returnCode; } catch (Exception connectEx) { Console.WriteLine("Connecting to " + vaultName + " caused an exception"); Console.Write(connectEx); return 99; } }