Перенаправить вывод (stdout, stderr) дочернего процесса в окно вывода в Visual Studio
В настоящий момент я запускаю командный файл из моей программы на С# с помощью:
System.Diagnostics.Process.Start(@"DoSomeStuff.bat");
То, что я хотел бы сделать, - перенаправить вывод (stdout и stderr) этого дочернего процесса в окно вывода в Visual Studio (в частности, Visual С# Express 2008).
Есть ли способ сделать это?
(Дополнительно: так, что он не все буферизуется, а затем выплевывается в окно "Вывод", когда заканчивается дочерний процесс.)
(BTW: В настоящий момент я могу заставить stdout (но не stderr) родительского процесса появиться в окне Output, сделав мою программу "Windows Application" вместо "Console Application". Это нарушает, если программа запускается за пределами Visual Studio, но это нормально в моем конкретном случае.)
Ответы
Ответ 1
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
на эти имена методов/свойств.
Ответ 2
Вариант этого работает для меня - установление этого сейчас, потому что мне жаль, что я не нашел его раньше.
Обратите внимание, что это всего лишь фрагмент, извлеченный из реального кода, поэтому могут быть тривиальные ошибки.
Метод основан на некотором коде 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();
}
Ответ 3
Что здесь происходит, так это то, что Visual Studio отображает вывод отладки из программы в окне вывода. То есть: если вы используете Trace.WriteLine, он появится в окне вывода из-за прослушивателя трассировки по умолчанию.
Как-то ваше приложение Windows Form (когда оно использует Console.WriteLine, я предполагаю, что вы используете Console.WriteLine) также пишет вывод отладки, и Visual Studio подбирает это.
Он не будет делать то же самое для дочерних процессов, если вы явно не зафиксируете вывод и не перенаправите его вместе с вашим выходом.
Ответ 4
Считаете ли вы использование DefaultTraceListener?
//Create and add a new default trace listener.
DefaultTraceListener defaultListener;
defaultListener = new DefaultTraceListener();
Trace.Listeners.Add(defaultListener);