如何在没有 WMI 的情况下获得在远程计算机上运行的进程的所有者

我正在创建远程任务管理器应用程序,并且正在尝试找出如何在没有 WMI 的情况下获得在远程计算机上运行的进程的进程所有者。使用 WMI 确实很容易,但速度太慢。我尝试使用 WTSQuerySessionInformation,但它仅适用于本地计算机。

为了更详细地说明,我的远程任务管理器应用程序将在工作站上运行,并将连接到另一个工作站以及同一网络中的服务器。将运行该应用程序的用户将是两台计算机上的管理员。

请问,您是否知道如何获得远程进程的所有者的另一种方法,或者对下面的代码进行一些改进/修复?

我的WMI版本(太慢了...)

public static Dictionary<Process, string> GetOwners(this IEnumerable<Process> processes)

{

        Dictionary<Process, string> result = new Dictionary<Process, string>();


        if (processes == null || processes.Count() == 0) { return result; }


        string select = "SELECT Handle, ProcessID FROM Win32_Process";

        select += processes.Count() <= 10 ? string.Format(" WHERE ProcessID = {0}", string.Join(" OR ProcessID = ", processes.Select(p => p.Id))) : string.Empty;


        ManagementScope scope = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", processes.ElementAt(0).MachineName));

        SelectQuery selectQuery = new SelectQuery(select);


        scope.Connect();


        using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, selectQuery))

        {

            using (ManagementObjectCollection objectCollection = searcher.Get())

            {

                foreach (ManagementObject managementObject in objectCollection)

                {

                    try

                    {

                        int id = Convert.ToInt32(managementObject["ProcessID"]);

                        string owner = managementObject.InvokeMethod("GetOwner", null, null)["User"]?.ToString();


                        result.Add(processes.Single(p => p.Id == id), owner);

                    }

                    catch

                    {

                    }

                }

            }

        }


        return result;

}

隔江千里
浏览 83回答 2
2回答

婷婷同学_

我建议迁移到较新的命名空间,因为System.Management它较旧、速度较慢且无法扩展。您所追求的新框架是Microsoft.Management.Infrastructure. 以下是Microsoft 文档对此进行了解释以及两者的示例。所以你会使用这样的东西:Using Microsoft.Management.Infrastructure;CimSession Session = CimSession.Create("computer_name");CimInstance Instance = Session.QueryInstances(@"root\cimv2", "WQL", "SELECT Name FROM Win32_ComputerSystem");foreach (CimInstance i in Instance){    Console.WriteLine(i.CimInstanceProperties["Name"].Value);}或者Using Microsoft.Management.Infrastructure;CimSession Session = CimSession.Create("computer_name");CimInstance Instance = Session.QueryInstances(@"root\cimv2", "WQL", "SELECT Name FROM Win32_ComputerSystem").First();Console.WriteLine(Instance.CimInstanceProperties["Name"].Value);我希望这能给你一些新的兔子洞来解决:-D 如果你还需要什么,请告诉我们:)

湖上湖

我创建了获取流程所有者的最终方法。它仍然不是超级快,但已经足够快了。与我的问题中的上述 WMI 方法相比,速度提升了 60% 以上,我相信仍有改进的空间。示例:从另一个 VLAN 中的工作站 获取数据(进程所有者、ID、句柄、可执行路径、描述、命令行),但同一网络域且大约具有 1 个 VLAN。200个进程:使用上面旧的 WMI 方法:大约。7000毫秒使用以下新方法:大约。2400毫秒方法:public struct WMIProcessProperties{    public string Owner;    public int ID;}public static async Task<Dictionary<Process, WMIProcessProperties>> GetWMIProperties(this IEnumerable<Process> processes){    Dictionary<Process, WMIProcessProperties> result = new Dictionary<Process, WMIProcessProperties>();    if (processes == null || processes.Count() == 0) { return result; }    string selectQuery = "SELECT Handle, ProcessID FROM Win32_Process";    selectQuery += processes.Count() <= 10 ? string.Format(" WHERE ProcessID = {0}", string.Join(" OR ProcessID = ", processes.Select(p => p.Id))) : string.Empty;    using (CimSession session = await Task.Run(() => CimSession.Create(processes.ElementAt(0).MachineName)))    {        List<CimInstance> instances = await Task.Run(() => session.QueryInstances(@"root\cimv2", "WQL", selectQuery).ToList());        List<Task<WMIProcessProperties>> tasks = new List<Task<WMIProcessProperties>>();        for (int i = 0; i < instances.Count; i++)        {            CimInstance currentInstance = instances[i];            tasks.Add(Task.Run(() =>            {                int id = Convert.ToInt32(currentInstance.CimInstanceProperties["ProcessID"].Value);                string owner;                using (CimMethodResult getOwnerResult = session.InvokeMethod(currentInstance, "GetOwner", null))                {                     owner = getOwnerResult.OutParameters["User"]?.Value?.ToString();                }                currentInstance.Dispose();                return new WMIProcessProperties { Owner = owner, ID = id };            }));        }        WMIProcessProperties[] wmiProcessProperties = await Task.WhenAll(tasks).ConfigureAwait(false);        for (int i = 0; i < wmiProcessProperties.Length; i++)        {            result.Add(processes.Single(p => p.Id == wmiProcessProperties[i].ID), wmiProcessProperties[i]);        }    }    return result;}
打开App,查看更多内容
随时随地看视频慕课网APP