Process.WaitForExit() 在重构后调用 taskkill 时要慢得多

本文关键字:taskkill 调用 WaitForExit 重构 Process | 更新日期: 2023-09-27 18:32:37

我正在重写我前段时间制作的应用程序。用户可用的功能之一是枚举当前在活动 Citrix 会话上运行的所有进程并显示它们(类似的 Windows 任务管理器(。问题是在用户计算机上查询tasklist时,以及输出此命令结果所花费的时间长度。

我的新版本代码采用了更加面向对象的方法,通过使用非静态类来表示SessionsProcs(进程(。

原始代码如下所示,就实际运行查询和检索输出结果所花费的时间长度而言,它运行得相当好:

旧代码:

    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",但这没有影响,所以我排除了这种可能性。

Process.WaitForExit() 在重构后调用 taskkill 时要慢得多

这是由于查询在服务器名称后不包含域名。

我使用 C# 秒表类运行了几个测试,似乎运行此查询:

TASKLIST /S XA7-17

比跑步慢很多

TASKLIST /S XA7-17.domain.co.uk

在服务器末尾包含域名后,我的查询与旧应用程序中一样快。