为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
隔江千里 2023-09-24 17:20:20
我正在创建远程任务管理器应用程序,并且正在尝试找出如何在没有 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;}
查看完整描述

2 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

我建议迁移到较新的命名空间,因为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 如果你还需要什么,请告诉我们:)


查看完整回答
反对 回复 2023-09-24
?
湖上湖

TA贡献2003条经验 获得超2个赞

我创建了获取流程所有者的最终方法。它仍然不是超级快,但已经足够快了。与我的问题中的上述 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;

}


查看完整回答
反对 回复 2023-09-24
  • 2 回答
  • 0 关注
  • 116 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信