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

时间:2016-01-29 16:54:44

标签: c# performance cmd tasklist

我正在重写我前一段时间制作的应用程序。用户可以使用的功能之一是枚举当前在活动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倍)版)。

新代码:

在ProcessHelper类中

    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”调用“任务列表”,但这没有任何影响,因此我已将此作为可能性进行排除。

1 个答案:

答案 0 :(得分:1)

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

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

TASKLIST /S XA7-17

比跑步慢很多

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

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