无法终止远程使用WMI和C#的过程 [英] Unable to remotely terminate a process using WMI and C#

查看:233
本文介绍了无法终止远程使用WMI和C#的过程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写这将在远程系统上终止服务,通过进程ID,如果失败就停止使用StopService方法的方法。我曾尝试调用上的ManagementObject的终止的方法的两种不同的方式,我得到两个不同的错误。这也是对我很重要,我能够得到来自终止方法的返回代码。



如果我直接申报ManagementPath到我要终止的过程中,我得到错误System.Management.ManagementException:无效的对象路径的行:



ManagementBaseObject processParams = processObj.InvokeMethod(终止(ManagementBaseObject )NULL,NULL);



如果我通过它寻找的进程ID我想终止得到ManagementObjectCollection和循环,我得到的在路线错误无效参数:



ManagementBaseObject termParams = currentObj.InvokeMethod(终止(ManagementBaseObject)NULL,NULL);



因此,在这两种情况下,我得到一个错误,当我尝试调用终止方法,但错误不同取决于我如何在到达对象(通过收集直接路径或循环)。



我不的认为的这是关系到SeDebugPrivilege,因为我相信我会。提示拒绝访问或不足特权,如果它是



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



<预类=郎-CS prettyprint-覆盖> 公众诠释KillServiceWMI(字符串服务名,字符串服务器名,字符串serverUser,串SERVERDOMAIN,串SERVERPASSWORD)
{
尝试
{
ConnectionOptions选项=新ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
options.Username = SERVERDOMAIN +\\+ serverUser;
options.Password = SERVERPASSWORD;

管理范围范围=新的管理范围(\\\\+服务器名+\\root\\cimv2选项);
Console.WriteLine(连接到范围);
scope.Connect();

Console.WriteLine(获得ManagementPath);
ManagementPath servicePath =新ManagementPath(Win32_Service.Name ='+服务名+');
Console.WriteLine(获得的ManagementObject);
的ManagementObject serviceObj =新的ManagementObject(范围,servicePath,新ObjectGetOptions());
Console.WriteLine(服务的名称是+ serviceObj [显示名称]的ToString());
Console.WriteLine(的服务进程ID为+ serviceObj [的ProcessID]的ToString());
ManagementPath processPath =新ManagementPath(Win32_Process.ProcessId ='+ serviceObj [的ProcessID] +');
的ManagementObject processObj =新的ManagementObject(范围,processPath,新ObjectGetOptions());
ManagementBaseObject processParams = processObj.InvokeMethod(终止(ManagementBaseObject)NULL,NULL);
INT RETURNCODE = System.Convert.ToInt32(processParams.Properties [返回值]值。);
返回RETURNCODE;
}
赶上(例外connectEx)
{
Console.WriteLine(连接到+服务器名+导致异常);
Console.Write(connectEx);
返回99;
}
}

代码,如果通过的进程集合我循环:



<预类=郎-CS prettyprint-覆盖> 公众诠释KillServiceWMI(字符串服务名,字符串服务器名,字符串serverUser,串SERVERDOMAIN,串SERVERPASSWORD)
{

{
ConnectionOptions选项=新ConnectionOptions();
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
options.Username = SERVERDOMAIN +\\+ serverUser;
options.Password = SERVERPASSWORD;

管理范围范围=新的管理范围(\\\\+服务器名+\\root\\cimv2选项);
Console.WriteLine(连接到范围);
scope.Connect();

Console.WriteLine(获得ManagementPath);
ManagementPath servicePath =新ManagementPath(Win32_Service.Name ='+服务名+');
Console.WriteLine(获得的ManagementObject);
的ManagementObject serviceObj =新的ManagementObject(范围,servicePath,新ObjectGetOptions());
Console.WriteLine(服务的名称是+ serviceObj [显示名称]的ToString());
Console.WriteLine(的服务进程ID为+ serviceObj [的ProcessID]的ToString());
的ObjectQuery serviceQuery =新的ObjectQuery(从Win32_Process的SELECT * WHERE的ProcessID ='+ serviceObj [的ProcessID]的ToString()+');
ManagementObjectSearcher serviceSearcher =新ManagementObjectSearcher(范围,serviceQuery);
ManagementObjectCollection serviceColl = serviceSearcher.Get();
INT RETURNCODE = 0;
的foreach(的ManagementObject currentObj在serviceColl)
{
如果(currentObj [的ProcessID]。的ToString()。等于(serviceObj [的ProcessID]。的ToString(),StringComparison.OrdinalIgnoreCase) )
{
Console.WriteLine(发现过程+ currentObj [的ProcessID]的ToString()+)终止......;

ManagementBaseObject termParams = currentObj.InvokeMethod(终止(ManagementBaseObject)NULL,NULL);
RETURNCODE = System.Convert.ToInt32(termParams.Properties [返回值]值。);
}
}
返回RETURNCODE;
}
赶上(例外connectEx)
{
Console.WriteLine(连接到+ VAULTNAME +导致异常);
Console.Write(connectEx);
返回99;
}
}


解决方案

我最终放弃了尝试使用终止方法上Win32_Process的,而是我用创建远程调用TaskKill.exe。因为返回的信息是现在的背后隐藏着taskkill.exe,然后我不得不再次获得进程列表,并认准了目标PID,以确保这个过程实际上终止。

  ConnectionOptions选项=新ConnectionOptions(); 
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
options.Username = SERVERDOMAIN +\\+ serverUser;
options.Password = SERVERPASSWORD;

管理范围范围=新的管理范围(\\\\+服务器名+\\root\\cimv2选项);
Console.WriteLine(连接到范围);
scope.Connect();

Console.WriteLine(获得ManagementPath);
ManagementPath servicePath =新ManagementPath(Win32_Service.Name ='+服务名+');
Console.WriteLine(获得的ManagementObject);
的ManagementObject serviceObj =新的ManagementObject(范围,servicePath,新ObjectGetOptions());
Console.WriteLine(服务的名称是+ serviceObj [显示名称]的ToString());
Console.WriteLine(的服务进程ID为+ serviceObj [的ProcessID]的ToString());

//使用进程ID来杀死TASKKILL
ObjectGetOptions processObjGetOpt =新ObjectGetOptions过程();
ManagementPath processPath =新ManagementPath(Win32_Process的);
ManagementClass processClass =新ManagementClass(范围,processPath,processObjGetOpt);
ManagementBaseObject processInParams = processClass.GetMethodParameters(创建);
processInParams [的CommandLine] =的String.Format(CMD / C \的taskkill / F / PID {0} \,serviceObj [的ProcessID]的ToString());
ManagementBaseObject outParams = processClass.InvokeMethod(创建,processInParams,NULL);
Console.WriteLine(为TASKKILL返回代码:+ outParams [的returnValue]);
INT RETURNCODE = System.Convert.ToInt32(outParams [的returnValue]);


I am trying to write a method that will terminate a service on a remote system, by process ID, if it fails to stop using the StopService method. I have tried two different ways of invoking the "Terminate" method on a ManagementObject, and I get two different errors. It's also important to me that I be able to get the return code from the Terminate method.

If I declare a ManagementPath directly to the process I want to terminate, I get the error "System.Management.ManagementException: Invalid object path" at line:

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

If I get a ManagementObjectCollection and loop through it looking for the Process ID I want to terminate, I get the error "Invalid parameter" at line:

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

So, in both cases, I get an error when I try to invoke the Terminate method, but the error differs depending on how I arrive at the object (direct path or loop through collection).

I don't think this is related to SeDebugPrivilege, as I believe I'd be getting "access denied" or "insufficient privilege" if it was.

Code if I attempt 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 loop through 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;
    }
}

解决方案

I eventually gave up trying to use the Terminate method on Win32_Process, and instead I'm using Create to call TaskKill.exe remotely. Because the return info is now hidden behind taskkill.exe, I then have to get the process list again and look for the target pid to make sure that the process was actually terminated.

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"]);

这篇关于无法终止远程使用WMI和C#的过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆