1

選択した .bat ファイルを実行するだけのコンソール ラッパー WPF gui を作成しようとしています。.bat ファイルからの出力を "ライブ" (cmd で実行されているかのように) 表示できるようにしたいと考えています。

テキストを追加して画面に送信する OutputDataReceived とイベント ハンドラーを調べましたが、画面に何かが表示される前に Process が終了するまで待機します。

.bat からの出力を「リアルタイム」で表示するにはどうすればよいですか?


これまでのコードのスニペット (これは形式です):

フォームには、1 つのボタン ( go) と 1 つの複数行テキスト フィールド ( textArea) があります。

private void go_Click(object sender, EventArgs e)
{
    ExecuteCommand();
}

public void ExecuteCommand()
{

    int ExitCode;
    ProcessStartInfo ProcessInfo;
    Process Process;

    //ProcessInfo = new ProcessStartInfo("cmd.exe", "/C z:\foo.bat");
    ProcessInfo = new ProcessStartInfo(@"z:\foo.bat"); ;

    ProcessInfo.CreateNoWindow = true;
    ProcessInfo.UseShellExecute = false;

    ProcessInfo.RedirectStandardError = true;
    ProcessInfo.RedirectStandardOutput = true;

    Process = new Process();
    Process.StartInfo = ProcessInfo;

    Process.OutputDataReceived += new DataReceivedEventHandler(OutputToTextArea);

    Process.Start();

    // Start the asynchronous read of the sort output stream.
    Process.BeginOutputReadLine();

    Process.WaitForExit();

    ExitCode = Process.ExitCode;
    Process.Close();
}

private int numOutputLines = 0;
private void OutputToTextArea(object sendingProcess, DataReceivedEventArgs outLine)
{
    // Collect the sort command output. 
    if (!String.IsNullOrEmpty(outLine.Data))
    {
        numOutputLines++;

        this.AppendToTextArea("[" + numOutputLines.ToString() + "] - " + outLine.Data + Environment.NewLine);
    }
}

private void AppendToTextArea(string s)
{
    if (this.textArea.InvokeRequired)
    {
        // It's on a different thread, so use Invoke.
        this.BeginInvoke (new MethodInvoker(() => textArea.AppendText(s)));
    } else {
        textArea.AppendText(s);
    }
}

私の foo.bat は単なる for ループです:

ECHO OFF

FOR /L %%i IN (1,1,10) DO (
   echo %%i
   ping -n 2 127.0.0.1 >nul
)
4

2 に答える 2

4

そうですね、現在ExecuteCommand、UI スレッド ( ) から直接呼び出される でプロセスが終了するのを待っているときに、メイン スレッド (UI スレッド) をブロックしていますgo_Click

新しいスレッドを開始する (または を使用するThreadPool) だけです (Winforms の例):

private void button1_Click(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(this.ExecuteCommand));
}

public void ExecuteCommand(object state)
{
    ...
}

WPF を使用している場合は、おそらくBackgroundWorker.

于 2013-01-29T12:56:12.480 に答える
1

シンプルにしたい場合は、/K 引数を指定してコマンド プロンプトを起動し、バッチ ファイルを渡すだけです。

string arguments = @"z:\foo.bat";

Process.Start("cmd.exe", "/K " + arguments);

cmd.exe /K が開き、コマンド プロンプトが表示され、foo.bat が実行されますが、画面に残ります。

于 2013-01-29T13:24:49.080 に答える