2

StopService メソッドの使用を停止できなかった場合に、リモート システムのサービスをプロセス ID で終了するメソッドを作成しようとしています。ManagementObject で「Terminate」メソッドを呼び出す 2 つの異なる方法を試しましたが、2 つの異なるエラーが発生しました。また、Terminate メソッドからリターン コードを取得できることも重要です。

終了したいプロセスに ManagementPath を直接宣言すると、次の行に「System.Management.ManagementException: Invalid object path」というエラーが表示されます。

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

ManagementObjectCollection を取得し、終了するプロセス ID を探してループすると、次の行に「無効なパラメーター」というエラーが表示されます。

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

1 に答える 1

1

結局、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"]);
于 2013-09-25T17:39:28.047 に答える