タスクを実行するために別のプログラムを呼び出す必要があるWindowsフォームアプリケーションを開発しています。このプログラムはコンソールアプリケーションであり、標準出力をコンソールからプログラムのTextBoxにリダイレクトする必要があります。
アプリケーションからプログラムを実行しても問題はありませんが、出力をアプリケーションにリダイレクトする方法がわかりません。イベントを使用してプログラムの実行中に出力をキャプチャする必要があります。
コンソールプログラムは、アプリケーションが停止し、テキストがランダムな間隔で絶えず変化するまで実行を停止するものではありません。私がやろうとしているのは、コンソールからの出力をフックして、イベントハンドラーをトリガーし、それを使用してTextBoxを更新することです。
C#を使用してプログラムをコーディングし、.NETフレームワークを使用して開発しています。元のアプリケーションは.NETプログラムではありません。
編集:これは私がやろうとしていることのサンプルコードです。最後のアプリでは、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);
}
これは私のために働く:
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
}
次のコードを使用できます
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();
O2 Platform (オープンソースプロジェクト)に多くのヘルパーメソッドを追加しました。これにより、コンソールの出力と入力を介して別のプロセスとのやり取りを簡単にスクリプト化できます( 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/ (このブログまた、新しいプロセスのコンソール出力を使用する方法の詳細が含まれています)
C#から.EXEファイルを実行し、DOSウィンドウからC#に結果を取得(パイプ)する方法 を参照してください。
時間を節約してくれたマークマックスハムの回答に感謝します。
Jon of All Tradesが気づいたように、IOストリームをリダイレクトするには、UseShellExecute
をfalseに設定する必要があります。そうでない場合、Start()
呼び出しはInvalidOperationException
。
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) ));
}