- PR -

他のプロセスの標準出力をリダイレクトする方法

1
投稿者投稿内容
カズ
会議室デビュー日: 2004/02/20
投稿数: 9
投稿日時: 2005-10-02 23:25
コマンドプロンプトをProcess.Start()で起動して、テキストボックスの内容を標準入力に渡し、標準出力から結果を取得したいです。
Process.StandardOutputを使用して出力を読み取ろうとしたのですが、うまく取得していないようです。
(コマンドプロンプトの\\\\c:>も出力されません。その後、dirコマンドを実行して確認しましたが、'dirプロセスが、存在しないパイプに書き込もうとしました。'というエラーがでます。)
検索したところ、出力を取得してその後プロセスが終了するまで待つサンプルばかり見つかり、今回のように入力と出力を繰り返すサンプルを見つけることが出来ませんでした。
何かヒントになることがありましたら教えていただけ無いでしょうか?
よろしくお願いします。
コード:
this.m_Process = new Process();
ProcessStartInfo info = this.m_Process.StartInfo;
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardInput = true;
info.FileName = "cmd.exe";

this.m_Process.Start();

this.m_OutThread = new Thread(new ThreadStart(this.OutputRead));
this.m_OutThread.Name = "output";
this.m_OutThread.Start();

private void OutputRead(){
	StreamReader reader = this.m_Process.StandardOutput;
	while(reader.Peek() != -1){
		this.OutputTextBox.Text += (string.Format("{0}",reader.ReadLine()));
	}
}
private void InputTextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) {
	if(e.KeyCode == Keys.Enter){
		this.m_Process.StandardInput.WriteLine(this.InputTextBox.Text);
	}
}


囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2005-10-03 01:48
こんにちは。

「うまく取得していない」とうはどういう状況ですか?

試していないので、推測で述べます。

子プロセスを開始した後、(this.m_Process.Start();)
すぐに別スレッドを開始して出力を読み取ろうとしていますよね?(this.m_OutThread.Start();)

子プロセスが出力を終わらないうちに、そのスレッドが StandardOutput を読み、Peek() が -1 を返したらどうなるでしょうか。
恐らく「うまく所得していない」でしょう。
「出力が終わらないうちに」どころか、「まだ子プロセスが一つも出力をしていないうちに」かもしれません。

ではどうしたら良いのか。
reader.Peek() が -1 を返すまで、ではなく、子プロセスが終了するまで出力を読み続ける、でしょう。(多分^^;
もう少し工夫がいるかもしれません。

カズ
会議室デビュー日: 2004/02/20
投稿数: 9
投稿日時: 2005-10-03 09:39
返信ありがとうございます。
囚人さんの仰る通りです。スレッドが先に終了しているようでした。
そこで、子プロセスが終了するまで読み取るように変更してみました。
後、別スレッドからTextBoxにアクセスするので、Invoke()も使用しました。
コード:
private void OutputRead(){
	StreamReader reader = this.m_Process.StandardOutput;
	while(!this.m_Process.HasExited){
		if(this.OutputTextBox.Created){
			AppendTextDelegate ad = new AppendTextDelegate(this.AppendText);
			object[] arg = new object[]{((char)reader.Read()).ToString()};
			this.OutputTextBox.Invoke(ad,arg);
		}
	}
}
private delegate void AppendTextDelegate(string s);
private void AppendText(string s){
	this.OutputTextBox.AppendText(s);
}


これで、一応うまくいきました。
しかし、ここからftpなどを立ち上げるとまったく出力が得られません。
('quit'と入力するとftpを終了するので、入力は渡すことができています。)
標準出力から出力を取れば出来ると思っていたのですが…
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-10-03 09:53
こんにちは、じゃんぬ です。

引用:

カズさんの書き込み (2005-10-03 09:39) より:

しかし、ここからftpなどを立ち上げるとまったく出力が得られません。
('quit'と入力するとftpを終了するので、入力は渡すことができています。)
標準出力から出力を取れば出来ると思っていたのですが…


とりあえず、当該スレッドは通っていることは確認できています?
本当に出力するデータがないだけなのかどうか絞り込みましょう。
StandardError からも出力されていないかな?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
どっとねっとふぁん
ぬし
会議室デビュー日: 2005/02/23
投稿数: 935
投稿日時: 2005-10-03 11:55
引用:

カズさんの書き込み (2005-10-03 09:39) より:

しかし、ここからftpなどを立ち上げるとまったく出力が得られません。
('quit'と入力するとftpを終了するので、入力は渡すことができています。)
標準出力から出力を取れば出来ると思っていたのですが…


ftpって動作結果等を表示しているのは標準出力ではなかったと思います。
結果をファイルに書き込むような指定は何かできたはず。。。
カズ
会議室デビュー日: 2004/02/20
投稿数: 9
投稿日時: 2005-10-03 22:33
じゃんぬさん、どっとねっとふぁんさん、ありがとうございます。

dir→ftp→quit(ftpの終了コマンド)→dir
と順にコマンドを打ち込むと2回目のdirコマンドも普通に出力されるので、スレッドの問題では無い気がします…

エラー出力は標準出力と同じ方法で取得しています

ftpの出力が標準出力では無いならこの方法では出来ませんね。
何とかできないものでしょうか…
1

スキルアップ/キャリアアップ(JOB@IT)