2010-09-04 4 views
11

На данный момент я начинаю пакетный файл из моей программы C# с:Перенаправление вывода (STDOUT, STDERR) дочернего процесса в окне вывода в Visual Studio

System.Diagnostics.Process.Start(@"DoSomeStuff.bat"); 

То, что я хотел бы быть способный сделать, - перенаправить вывод (stdout и stderr) этого дочернего процесса в окно вывода в Visual Studio (в частности, Visual C# Express 2008).

Есть ли способ сделать это?

(Дополнительно:. Таким образом, что это все не помещаются в буфер, а затем плюнул в окно Output, когда дочерний процесс заканчивается)


(КСТАТИ: На данный момент я могу получить стандартный вывод (но не STDERR) родителя появится в окне «Вывод», сделав мою программу «Приложением Windows» вместо «Консольного приложения». Это прерывается, если программа запускается за пределами Visual Studio, но это нормально в моем конкретном случае .)

+0

Все части находятся здесь. Перенесите вывод для процесса, используйте Trace, чтобы получить его в окне Output. –

+0

Вы поняли, как перенаправить выход дочернего процесса? Ответы, приведенные ниже, могут перенаправить вывод родительского процесса, но не дочернего. – Fiona

ответ

20
process.StartInfo.CreateNoWindow = true; 
process.StartInfo.UseShellExecute = false; 
process.StartInfo.RedirectStandardOutput = true; 
process.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data); 
process.Start(); 
process.BeginOutputReadLine(); 

process.WaitForExit(); 

Та же самая идея для Error, просто заменить Output в этих именах метод/собственность.

+6

Этот ответ в основном прав. Его нет. В частности: 'Start' вызов до' Begin ... ReadLine' и 'WaitForExit' впоследствии. Кроме того, установка «RedirectStandardInput» в true исправила проблему, вызванную одной из программ (в частности, plink) в пакетном файле, требующем действительного stdin, хотя он и не использовал его. –

+0

'WaitForExit()' может вызвать бесконечное ожидание. Всегда вызывать метод с таймаутом: 'process.WaitForExit (10000)' => ждет 10 секунд. –

-3

Считаете ли вы использование DefaultTraceListener?

//Create and add a new default trace listener. 
    DefaultTraceListener defaultListener; 
    defaultListener = new DefaultTraceListener(); 
    Trace.Listeners.Add(defaultListener); 
+2

Это даже не * удаленно * ответ на мой вопрос. И со связанной страницы MSDN: «Экземпляр этого класса автоматически добавляется в коллекции Debug.Listeners и Trace.Listeners. Явное добавление второго DefaultTraceListener вызывает дублирующиеся сообщения в окне вывода отладчика и дублирует окна сообщений для утверждений.», Что делает ваш ответ хуже, чем абсолютно бесполезный. –

+4

Месть вниз, а? Оставайтесь классными, GenEric35. –

+0

+1 для объяснения MSDN для Андерва – prabhakaran

2

Что здесь происходит, так это то, что Visual Studio отображает вывод отладки из программы в окне вывода. То есть: если вы используете Trace.WriteLine, он появится в окне вывода из-за прослушивателя трассировки по умолчанию.

Как-то ваше приложение Windows Form (когда оно использует Console.WriteLine, я предполагаю, что вы используете Console.WriteLine) также пишет вывод отладки, и Visual Studio подбирает это.

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

+0

Это в основном то, что я пытаюсь спросить - как вы делаете последний бит? (И я понял, что мне не хватает этого из моего вопроса: как это сделать «как это бывает»?) –

8

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

Методика основана на некотором коде MSDN. То, что я не смог выяснить, - как получить окно вывода для обновления «на лету». Он не обновляется до тех пор, пока эта задача не вернется.

// Set this to your output window Pane 
private EnvDTE.OutputWindowPane _OutputPane = null; 

// Methods to receive standard output and standard error 

private static void StandardOutputReceiver(object sendingProcess, DataReceivedEventArgs outLine) 
{ 
    // Receives the child process' standard output 
    if (! string.IsNullOrEmpty(outLine.Data)) { 
     if (_OutputPane != null) 
      _OutputPane.Write(outLine.Data + Environment.NewLine); 
    } 
} 

private static void StandardErrorReceiver(object sendingProcess, DataReceivedEventArgs errLine) 
{ 
    // Receives the child process' standard error 
    if (! string.IsNullOrEmpty(errLine.Data)) { 
     if (_OutputPane != null) 
      _OutputPane.Write("Error> " + errLine.Data + Environment.NewLine); 
    } 
} 

// main code fragment 
{ 
    // Start the new process 
    ProcessStartInfo startInfo = new ProcessStartInfo(PROGRAM.EXE); 
    startInfo.Arguments = COMMANDLINE; 
    startInfo.WorkingDirectory = srcDir; 
    startInfo.UseShellExecute = false; 
    startInfo.RedirectStandardOutput = true; 
    startInfo.RedirectStandardError = true; 
    startInfo.CreateNoWindow = true; 
    Process p = Process.Start(startInfo); 
    p.OutputDataReceived += new DataReceivedEventHandler(StandardOutputReceiver); 
    p.BeginOutputReadLine(); 
    p.ErrorDataReceived += new DataReceivedEventHandler(StandardErrorReceiver); 
    p.BeginErrorReadLine(); 
    bool completed = p.WaitForExit(20000); 
    if (!completed) 
    { 
     // do something here if it didn't finish in 20 seconds 
    } 
    p.Close(); 
} 
+0

Это не будет получать stdout и stderror в правильном порядке. – paulm

+0

@paulm, что вы подразумеваете под этим, не получит правильный заказ? Этот код не работает для меня при перенаправлении stderr (stdout работает). Любая идея почему? – rboy

+0

Используйте ответ из моего вопроса - это не приведет к тому, что stderr и stdout будут в правильном порядке, то есть, если приложение выйдет, выйдет из системы, вы ошибетесь, вы можете выйти, выйти, заблудиться, ошибиться и т. Д. – paulm

Смежные вопросы