Process.WaitForExit() 在重构后调用 taskkill 时要慢得多
本文关键字:taskkill 调用 WaitForExit 重构 Process | 更新日期: 2023-09-27 18:32:37
我正在重写我前段时间制作的应用程序。用户可用的功能之一是枚举当前在活动 Citrix 会话上运行的所有进程并显示它们(类似的 Windows 任务管理器(。问题是在用户计算机上查询tasklist
时,以及输出此命令结果所花费的时间长度。
我的新版本代码采用了更加面向对象的方法,通过使用非静态类来表示Sessions
和Procs
(进程(。
原始代码如下所示,就实际运行查询和检索输出结果所花费的时间长度而言,它运行得相当好:
旧代码:
public static Dictionary<string, string> GetProcs(string server, string sessID)
{
SecureString ss = CreatePW();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C tasklist /S " + server + " /FI '"SESSION eq " + sessID + "'" /FO CSV /NH")
{
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = @"C:'windows'system32",
Verb = "runas",
Domain = "BARDOM1",
UserName = "zzkillcitrix",
Password = ss
};
List<string> procList = new List<string>();
Process proc = Process.Start(startInfo);
proc.OutputDataReceived += (x, y) => procList.Add(y.Data);
proc.BeginOutputReadLine();
proc.WaitForExit();
// Create a new ditionary ...
Dictionary<string, string> procDict = new Dictionary<string, string>();
for (int i = 0; i < procList.Count - 1; i++)
{
if (procDict.ContainsKey(procList[i].Split(',')[0].Trim('"')))
{
// Do nothing
}
else
{
procDict.Add(procList[i].Split(',')[0].Trim('"'), procList[i].Split(',')[1].Trim('"'));
}
}
return procDict;
}
整个应用程序非常混乱,所以我重写了大部分内容,但我唯一担心的是检索当前进程列表的新方法要慢得多(可能比旧版本慢 4 - 5 倍左右(。
新代码:
在进程帮助程序类中
public static List<Proc> GetProcList(Session session)
{
// Get the current tasks
List<string> processQueryResult = TaskList(session);
List<Proc> procList = new List<Proc>();
foreach (var processDetails in processQueryResult)
{
// Only create the Proc if the process is in the 'valid' array ...
// Get the procname
string procName = processDetails.Split(',')[0].Trim('"').ToUpper();
// Make sure it's position is not -1 ...
int pos = Array.IndexOf(MyGlobals.ProcArray, procName);
if (pos > -1)
{
int procId = Int32.Parse(processDetails.Split(',')[1].Trim('"'));
Proc p = new Proc(procName, procId, session.ServerName, session.ID);
procList.Add(p);
SupportMI.Trace = "--adding" + p.Name + "--";
}
}
return procList;
}
private static List<string> TaskList(Session session)
{
string cmdIn = "tasklist /S " + session.ServerName + " /FI '"SESSION eq " + session.ID + "'" /FO CSV /NH";
List<string> cmdOut = Cmd.StdOutAdminList(cmdIn);
return cmdOut;
}
在 Cmd 类中
public static List<string> StdOutAdminList(string args)
{
List<string> cmdOut = new List<string>();
SecureString ss = pw();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C " + args)
{
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = @"C:'windows'system32",
Verb = "runas",
Domain = "BARDOM1",
UserName = "zzkillcitrix",
Password = ss
};
cmdOut = ExecuteListCommand(startInfo);
return cmdOut;
}
private static List<string> ExecuteListCommand(ProcessStartInfo startInfo)
{
List<string> procList = new List<string>();
Process p = Process.Start(startInfo);
p.OutputDataReceived += (x, y) => procList.Add(y.Data);
p.BeginOutputReadLine();
p.WaitForExit();
return procList;
}
可能的原因
在新版本的程序中,我还引入了几个新对象(例如,用于存储有关单独进程信息的 Session 类和 Proc 类(。添加这些额外的类是否有可能减慢 Process.WaitForExit(( 方法的速度?
经过一些调试,程序相对于旧代码的速度似乎变慢的时间点是调用Process.WaitForExit()
- 除了 ProcessStartInfo 详细信息之外,是否有任何影响此方法调用的内容? 如果没有,那么我很困惑,因为我将 ProcessStarInfos 设置为相同的设置,但新代码仍然有延迟。
我的另一个想法是,也许添加更多对象,意味着传递更多参数,正在减慢整个应用程序的速度,这以某种方式以上述方式表现出来。
任何关于为什么会发生这种情况的见解都非常感谢。如果我可以提供更多详细信息或代码,或运行任何测试,请告诉我。
我还考虑过直接从Process
而不是"cmd"调用"tasklist",但这没有影响,所以我排除了这种可能性。
这是由于查询在服务器名称后不包含域名。
我使用 C# 秒表类运行了几个测试,似乎运行此查询:
TASKLIST /S XA7-17
比跑步慢很多
TASKLIST /S XA7-17.domain.co.uk
在服务器末尾包含域名后,我的查询与旧应用程序中一样快。