2015-09-16 16 views
8

私は、その進捗に関するデータをコマンドラインに書き込む第三者のDOSプロセスを持っています。 進捗状況に反応したい。通常、私は通常、この作品 プロセスの出力を取得することが可能

RedirectStandardOutput = trueRedirectStandardError = trueProcessを使用して、

.OutputDataReceived +=xyzOutputDataReceived; 
.ErrorDataReceived += xyzErrorDataReceived; 
.Start(); 
.BeginOutputReadLine(); 
.BeginErrorReadLine(); 
でしょう。私はDataReceivedEventArgとして必要なものを手に入れました。

この場合、プロセスは書いた行と同じ行を更新しているように見えます(その可能性はありますか?)ので、15%、15%の変更が18%に書き込まれます。実行の終了時にのみ、データがStandardOutputにフラッシュされているように見えます。

また、データをテキストファイル(たとえばodb.exe >> output.txt)にパイプしてみると、何も表示されません。

一時データを取得する方法はありますか?

質問は標準出力を取得することではなく、同期して非同期にうまく動作します。それは、私が変更できないプロセスから出力を得る方法であり、標準ストリームに出力されていないようです。

+1

C#アプリケーションでは、 "Console.SetCursorPosition()'関数(https://msdn.microsoft.com/de-de/library)を使用して、同じ行にあるものを上書きすることもできます。 /system.console.setcursorposition%28v=vs.110%29.aspx)。私はなぜあなたのケースで 'OutputDataReceived'イベントを引き起こさないのか分かりません。 –

+0

http://stackoverflow.com/questions/186822/capturing-console-output-from-a-net-application-c 、ほとんど同じ質問 – Thorarins

+0

@Thorarins同じではありません。このQには、明らかに改行を印刷せず、標準出力をフラッシュしないアプリケーションがあります。そのため、 'OutputDataReceived'は起動されません。 –

答えて

0

私は、これはあなたが探しているものだと思います:C# : Redirect console application output : How to flush the output?

私が間違っている場合は私に知らせてください。

+0

その解決策は役に立たなかった。私はそれを試しましたが、それはまた、プログラマーが終了した5分後の最初の入力を取得します。 (主なことは、StreamReader.BeginReadを出力ストリームに接続するように思われる...) – Offler

0

juharrさんのように、コンソールをスクレイプするためにWin32を使用する必要があります。 幸いにも、自分でコードを書く必要はありません。この記事のバッファリーダーを使用することができます:https://stackoverflow.com/a/12366307/5581231

BufferReaderは標準出力から読み取ります。私はwpfまたはwinformsアプリケーションを作成していると思いますので、DOSアプリケーションのコンソールウィンドウへの参照を取得する必要があります。このために、Win32 API呼び出しのAttachConsoleを使用します。

[System.Runtime.InteropServices.DllImport("kernel32.dll")] 
private static extern bool AttachConsole(int pid); 

私は、使用法を示す小さなサンプルプログラムを作成しました。 exeを起動し、コンソールに接続します。次に、ウィンドウ全体を1秒に1回掻き集め、出力をデバッガの出力ウィンドウにダンプします。プログラムの進行状況を追跡するために使用できるキーワードなどのコンソールコンテンツを検索するには、これを変更できる必要があります。あるいは、それをテキストフィールドやUIの何かにダンプすることができます。

var process = Process.Start(@"..path to your exe....");  
//Wait for the DOS exe to start, and create its console window 
while (process.MainWindowHandle == IntPtr.Zero) 
{ 
    Thread.Sleep(500); 
} 

//Attach to the console of our DOS exe 
if (!AttachConsole(process.Id)) 
    throw new Exception("Couldn't attach to console"); 

while (true) 
{ 
    var strings = ConsoleReader.ReadFromBuffer(0, 0, 
        (short)Console.BufferWidth, 
        short)Console.BufferHeight); 
    foreach (var str in strings. 
        Select(s => s?.Trim()). 
        Where(s => !String.IsNullOrEmpty(s))) 
{ 
    Debug.WriteLine(str);   
} 
Thread.Sleep(1000); 
} 

Good Luck!

関連する問題