System.Diaganostics.Process (когда один процесс внутренне использует другой)

Я использую C# System.Diagnostics.Process для мониторинга вывода утилиты командной строки.

Процесс, который я отслеживаю «внутренне», запускает второй процесс, и как только он это делает, я больше не получаю выходных данных от объекта процесса.

Что расстраивает, так это то, что если вы выполняете ту же самую команду (которую я запускаю с объектом System.Diagnostics.Process) с помощью cmd.exe (вручную), консоль выводит каждую строку, которую мне нужно видеть в моем приложении C#!

Однако, если я (в целях тестирования) запускаю cmd.exe с объектом System.Diagnostics.Process и запускаю команду, она все равно прекращает вывод в том же месте, что и ранее (запуск process1.exe напрямую); в момент использования второго .exe. Я думал, что этот тест объединит все выходные данные всех задействованных процессов, но этого не произошло. Как я могу получить весь этот вывод в своем приложении C#?


person Lonnie Best    schedule 18.01.2010    source источник


Ответы (2)


Причина этого в том, что System.Diagnostics.Process буквально отслеживает только процесс, к которому он подключен.

Один из способов обойти эту проблему — вывести первое приложение при запуске второго приложения, а при получении этого вывода отслеживать из основного приложения процесс создания процесса из (теперь третьего) приложения. Как только третье приложение будет запущено, оно должно появиться в массиве System.Diagnostics.Process.GetProcesses(), после чего вы сможете присоединиться к его событию OutputDataReceived.

Тогда ваш код будет выглядеть примерно так (не проверено):

private void firstProcess_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
    if (e.Data == "Starting next process")
    {
        System.Diagnostics.Process newProcess = null;

        while (newProcess == null)
        {
            System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses();

            foreach (System.Diagnostics.Process proc in procs)
            {
                if (proc.ProcessName == "newProcess")
                {
                    newProcess = proc;
                    break;
                }
            }

            System.Threading.Thread.Sleep(100);
        }

        newProcess.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(newProcess_OutputDataReceived);
    }
}

void newProcess_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
    // Do something with your data received here.
}

Обратите внимание, что это всего лишь пример, и если ваш третий процесс не запустится или завершится слишком быстро, то этот метод зависнет в бесконечном цикле. Этот пример просто предназначен для того, чтобы предоставить вам знания для создания чего-то, что работает в вашем конкретном случае, с которым я не совсем знаком. Вы должны, как минимум, убедиться, что цикл while не будет продолжаться вечно, и, вероятно, вы также захотите внести некоторые другие корректировки.

РЕДАКТИРОВАТЬ: В качестве альтернативы, если вы не можете изменить исходный код для первого приложения, вы можете просто создать новый поток, который постоянно отслеживает таким образом (используя цикл while) и обрабатывает вывод из третьего процесса в отдельном классе или просто перенаправил вывод из третьего процесса в обработчик для вывода второго процесса, чтобы у вас мог быть один метод, обрабатывающий все выходные данные для обоих процессов.

person Nathan Wheeler    schedule 18.01.2010
comment
Во-первых, я поражен тем, как быстро вы ответили с такой подробностью, и я очень ценю вашу помощь. По выходным данным первого процесса я могу определить точку, в которой был запущен второй процесс. - person Lonnie Best; 19.01.2010
comment
К сожалению, в среде .Net нет объекта, который был бы столь же хорош в качестве консолидатора вывода процесса, как cmd.exe (при запуске вручную). - person Lonnie Best; 19.01.2010
comment
Спасибо за ваши усилия, но я все равно столкнулся с этим: " title="c ​​перенаправить стандартный вывод уже запущенного процесса"> stackoverflow.com/questions/2095826/ - person Lonnie Best; 20.01.2010

Вам вообще нужно запускать cmd.exe? Разве вы не можете просто инициировать процесс rsync непосредственно в своем процессе, а затем использовать что-то вроде методов, описанных в этот вопрос, чтобы получить результаты выполнения команды, чтобы вы могли работать с ними в своем коде?

person glenatron    schedule 18.01.2010
comment
Нет, вместо этого я только попытался запустить cmd.exe, потому что надеялся, что он покажет все выходные данные всех процессов. Сначала я попробовал это так, как вы упоминаете, и вывод (с использованием методов, указанных в вопросе, на который вы ссылались) прекратился после того, как первый процесс начал использовать второй процесс, который первый процесс вызывает внутри. - person Lonnie Best; 19.01.2010