Process.WaitForExit() 重构后调用 Taskkill 时速度慢得多

Process.WaitForExit() Much Slower After Refactor When Calling Taskkill

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

我的新版本代码采用了更加面向对象的方法,使用非静态 classes 来表示 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 倍)旧版本)。


新代码:

在 ProcessHelper class

    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;
    }

在命令中class

    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 class 和 Proc class 来存储有关单独进程的信息)。添加这些额外的 classes 是否有可能减慢 Process.WaitForExit() 方法的速度?

经过一些调试,程序相对于旧代码变慢的点似乎是在调用 Process.WaitForExit() 时 - 除了 ProcessStartInfo 细节之外,还有什么影响此方法调用吗?如果不是,那么我很困惑,因为我将 ProcessStarInfos 设置为相同的设置,但新代码仍然有延迟。

我的另一个想法是,也许添加更多对象,意味着传递更多参数,正在减慢整个应用程序,这在某种程度上以上述方式表现出来。

如果能深入了解为什么会发生这种情况,我们将不胜感激。如果我可以提供更多详细信息或代码,或者 运行 任何测试,请告诉我。

我也考虑过直接从 Process 调用 "tasklist" 而不是 "cmd",但这没有影响,所以我排除了这种可能性。

这是因为查询没有在服务器名称后面包含域名。

我 运行 使用 C# Stopwatch class 进行了几次测试 class,似乎 运行 这个查询:

TASKLIST /S XA7-17

比运行

慢很多

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

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