Process.WaitForExit() намного медленнее после рефакторинга при вызове Taskkill

Я нахожусь в процессе переписывания заявления, которое я сделал некоторое время назад. Одной из функций, доступных пользователям, является перечисление всех процессов, которые в данный момент выполняются в активном сеансе Citrix, и их отображение (аналог Windows Task Manager). Проблема в том, что при запросе 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 раз медленнее, чем старая версия).


НОВЫЙ КОД:

В классе 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 ответ

Решение

Это было связано с тем, что запрос не включал доменное имя после имени сервера.

Я провел несколько тестов, используя класс C# Stopwatch, и кажется, что этот запрос выполняется:

TASKLIST /S XA7-17

Намного медленнее, чем бег

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

После включения доменного имени в конце сервера мои запросы выполняются так же быстро, как и в старом приложении.

Другие вопросы по тегам