2013-09-24 4 views
2

Я пытаюсь написать метод, который прекратит службу в удаленной системе по идентификатору процесса, если он не сможет остановить использование метода StopService. Я пробовал два разных способа вызова метода «Terminate» в ManagementObject, и я получаю две разные ошибки. Для меня также важно, чтобы я мог получить код возврата из метода Terminate.Не удается удаленно завершить процесс с использованием WMI и C#

Если я объявляю ManagementPath непосредственно к процессу, я хочу кончить, я получаю ошибку «System.Management.ManagementException: Неверный путь объекта» в строке:

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

Если я получаю ManagementObjectCollection и цикл через него ищет идентификатор процесса, я хочу кончить, я получаю ошибку «Неверный параметр» в строке:

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

Рискуя задать глупый вопрос - это должно быть WMI/C#? Вы знаете, что это можно сделать с помощью PSEXEC от sysinternals? – Leptonator

+0

Да, я знаю, что могу использовать psexec и добираться до него таким образом. В этом случае это метод для веб-приложения, которое используется для управления связкой серверов. Некоторые из них, чтобы быть деликатными, «pokey», и поэтому их службы не останавливаются, когда им приказано делать это с WMI. Поэтому Operations просит меня добавить в приложение функцию «убить», чтобы после попытки (и неудачи) прекратить услугу дважды дважды она пытается завершить процесс. – Formica

+0

@paqogomez, у меня есть ощущение, что вы прочитали [этот мета-вопрос] (http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles), и это что мотивирует ваши недавние предложенные изменения. Прочитайте раздел [наивысший рейтинг] (http://meta.stackexchange.com/a/130208), который начинается с «Единственный раз, когда вы должны использовать теги в своем названии, когда они являются * органическими для разговорный тон названия * "(акцент мой). –

ответ

1

я в конце концов отказался от попыток использовать Прервать метод на Win32_Process, и вместо этого я использую 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"]); 
Смежные вопросы