Перенаправить вывод консоли в текстовое поле в отдельной программе
Я разрабатываю приложение Windows Forms, которое требует от меня вызова отдельной программы для выполнения задачи. Программа представляет собой консольное приложение, и мне нужно перенаправить стандартный вывод с консоли на TextBox в моей программе.
У меня нет проблем с выполнением программы из моего приложения, но я не знаю, как перенаправить вывод в мое приложение. Мне нужно захватить вывод во время работы программы с помощью событий.
Консольная программа не предназначена для остановки до тех пор, пока мое приложение не остановится и текст не будет изменяться в случайном порядке. То, что я пытаюсь сделать, это просто вывести из консоли консоль, чтобы вызвать обработчик событий, который затем может быть использован для обновления TextBox.
Я использую С# для кодирования программы и использования платформы .NET для разработки. Исходное приложение не является программой .NET.
EDIT:
Вот пример кода того, что я пытаюсь сделать. В моем последнем приложении я заменил Console.WriteLine кодом для обновления TextBox. Я попытался установить точку останова в обработчике событий, и это даже не достигнуто.
void Method()
{
var p = new Process();
var path = @"C:\ConsoleApp.exe";
p.StartInfo.FileName = path;
p.StartInfo.UseShellExecute = false;
p.OutputDataReceived += p_OutputDataReceived;
p.Start();
}
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(">>> {0}", e.Data);
}
Ответы
Ответ 1
Это работает для меня:
void RunWithRedirect(string cmdPath)
{
var proc = new Process();
proc.StartInfo.FileName = cmdPath;
// set up output redirection
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.EnableRaisingEvents = true;
proc.StartInfo.CreateNoWindow = true;
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
// output will be in string e.Data
}
Ответ 2
Вы можете использовать следующий код
MemoryStream mem = new MemoryStream(1000);
StreamWriter writer = new StreamWriter(mem);
Console.SetOut(writer);
Assembly assembly = Assembly.LoadFrom(@"C:\ConsoleApp.exe");
assembly.EntryPoint.Invoke(null, null);
writer.Close();
string s = Encoding.Default.GetString(mem.ToArray());
mem.Close();
Ответ 3
Смотрите Как запустить .EXE файл из С# и получить (передать) результаты из окон DOS обратно в С#
Ответ 4
Я добавил несколько вспомогательных методов в O2 Platform (проект с открытым исходным кодом), которые позволяют вам легко script взаимодействовать с другой процесс через консольный вывод и ввод (см. http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs)
Также полезно использовать API, который позволяет просматривать вывод консоли текущего процесса (в существующем элементе управления или всплывающем окне). См. Это сообщение в блоге для более подробной информации: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (этот блог также содержит сведения о том, как использовать консольный вывод новых процессов)
Ответ 5
Спасибо Марку Максэму за ответ, который сэкономил мне время!
Как заметил Jon of All Trades, для UseShellExecute
должно быть установлено значение false, чтобы перенаправлять потоки ввода-вывода, в противном случае вызов Start()
вызывает InvalidOperationException
.
Вот моя модификация кода, где txtOut
- txtOut
поле только для txtOut
в WPF
void RunWithRedirect(string cmdargs)
{
var proc = new Process()
{
StartInfo = new ProcessStartInfo("cmd.exe", "/k " + cmdargs)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
},
EnableRaisingEvents = true
};
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
Dispatcher.BeginInvoke(new Action( () => txtOut.Text += (Environment.NewLine + e.Data) ));
}