无法使用WMI和C#远程终止进程

我正在尝试编写一个方法,如果它无法停止使用StopService方法,将按进程ID终止远程系统上的服务。 我尝试了两种不同的方法来调用ManagementObject上的“Terminate”方法,我得到两个不同的错误。 我能够从Terminate方法获取返回码对我来说也很重要。

如果我直接向我想要终止的进程声明一个ManagementPath,我会在行中收到错误“System.Management.ManagementException:Invalid object path”:

ManagementBaseObject processParams = processObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);

如果我得到一个ManagementObjectCollection并在其中循环查找我想要终止的进程ID,我会在行中收到错误“Invalid parameter”:

ManagementBaseObject termParams = currentObj.InvokeMethod("Terminate", (ManagementBaseObject)null, null);

因此,在这两种情况下,当我尝试调用Terminate方法时出现错误,但错误因我到达对象的方式而不同(直接路径或循环收集)。

我不认为这与SeDebugPrivilege有关,因为我相信如果有的话,我将获得“访问被拒绝”或“权限不足”。

代码,如果我尝试直接指定进程的路径:

 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; } } 

代码,如果我遍历一系列进程:

 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; } } 

我最终放弃尝试在Win32_Process上使用Terminate方法,而是使用Create来远程调用TaskKill.exe。 因为返回信息现在隐藏在taskkill.exe后面,所以我必须再次获取进程列表并查找目标pid以确保该进程实际上已终止。

 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()); // use processid to kill process with taskkill ObjectGetOptions processObjGetOpt = new ObjectGetOptions(); ManagementPath processPath = new ManagementPath("Win32_Process"); ManagementClass processClass = new ManagementClass(scope, processPath, processObjGetOpt); ManagementBaseObject processInParams = processClass.GetMethodParameters("Create"); processInParams["CommandLine"] = string.Format("cmd /c \"taskkill /f /pid {0}\"", serviceObj["ProcessId"].ToString()); ManagementBaseObject outParams = processClass.InvokeMethod("Create", processInParams, null); Console.WriteLine("Return code for taskkill: " + outParams["returnValue"]); int returnCode = System.Convert.ToInt32(outParams["returnValue"]);