【发布时间】:2019-05-13 11:25:00
【问题描述】:
我有以下函数可以将进程信息提取到 DataTable 中:
public DataTable getProcesses()
{
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Name");
dt.Columns.Add("Path");
dt.Columns.Add("User");
dt.Columns.Add("Priority");
string pid = "-";
string name = "-";
string path = "-";
string priort = "-";
string user = "-";
string query = "Select * From Win32_Process";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject proc in processList)
{
pid = proc["ProcessID"].ToString();
name = proc["Name"].ToString();
if (proc["ExecutablePath"] != null)
{
path = proc["ExecutablePath"].ToString();
priort = proc["Priority"].ToString();
}
string[] argList = new string[2];
int returnVal = Convert.ToInt32(proc.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return DOMAIN\user
user = argList[1] + "\\" + argList[0];
}
dt.Rows.Add(pid, name, path, user, priort);
}
return dt;
}
这最终会奏效并给我想要的回报,但执行需要 20-30 秒。
我想知道是否有任何方法可以优化功能,或者特别是查询,这很可能是“延迟”的来源。
编辑
在完成 cmets 中建议的一些事情后,平均时间已降至 15-20 秒,但这仍然太长了。最多4-5秒是可以忍受的。我还没有更改查询,有什么办法可以让它更快吗?
编辑 2
在应用@NicoRiff 建议的一些更改后,仍然获得相同的运行时间,我进行了一些调试以查看实际花费了这么长时间。原来它是特定的一行:int returnVal = Convert.ToInt32(proc.InvokeMethod("GetOwner", argList));,这将使我成为“拥有”每个进程的用户。
这条线大约需要 60 毫秒,而其他所有线需要 1-2 毫秒。超过 200 次迭代(这是我拥有的进程数,我只能想象使用更大的列表会花费的时间),总共需要大约 12-13 秒(仅针对那一行),给出 15-20总计。
既然我已经“挑出”了问题,我该如何优化该功能?
【问题讨论】:
-
30 秒的延迟几乎总是环境问题。有一类软件会在程序员的机器上看到一个突然出现的可执行文件,然后立即戳到下一个进程时,它会永远在程序员的机器上造成这样的问题。将其关闭并重试。
-
我试过这个(我认为我关闭了正确的东西)并将时间减少到 15 秒,但这仍然很长。还有其他可能的原因吗?
-
看看如果你使用
.GetOwnerSid而不是.GetOwner,事情是否会变得更快,看看将SID映射到帐户是否是导致速度变慢的可能原因。还可以通过在 Powershell 中执行操作来检查基本查询本身是否有任何问题(gwmi win32_process立即在我的机器上返回;由于out参数,调用.GetOwner涉及更多一点)。 -
.GetOwnerSid并没有变得更快,也没有真正给我所需的输出。我检查了 powershell 上的查询,它立即运行,但显示整个输出大约需要 7-8 秒 - 不会冻结或任何东西。