ShellExecute等で実行したプログラムの出力結果を取得したい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

ShellExecute等で実行したプログラムの出力結果を取得したい

#1

投稿記事 by MoNoQLoREATOR » 11年前

コンソールアプリケーションを実行すると、コマンドプロンプトにその結果が出力されますよね。
あれを、ShellExecute等で実行したときに取得したいわけです。

しかし、ファイルに出力してそれを読み込むという方法しかみつかりません。
できれば直接取得したいのですが、どうすればよいのでしょうか。

さらに、ShellExecuteではなくCreateProcessを使用する必要があるという記述も目にしました。
CreateProcessで実行したウインドウを非表示に設定する方法がわからなかったためShellExecuteを採用したのですが、できればウインドウは非表示にしたいですね。

また、実行したいプログラムは自分が作ったものではないということを前提としています。


よろしくお願いいたします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#2

投稿記事 by softya(ソフト屋) » 11年前

CREATE_NO_WINDOWでCreateProcessすれば良いんじゃないでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#3

投稿記事 by ISLe » 11年前

子プロセスの標準入出力にアクセスする方法は一般的に「パイプ」と呼ばれます。
標準入出力のリダイレクトと説明している場合もあります。

「Win32 コンソール パイプ」というキーワードで検索するとサンプルコードがたくさん見付かると思います。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#4

投稿記事 by MoNoQLoREATOR » 11年前

返信ありがとうございます。
>>ソフト屋さん
仰るとおりです。見逃していたようです。

>>ISLeさん
おかげ様でアルゴリズムは掴めました。
管理クラスも作って動作テストをしてみると、しかしCreateProcessの部分でエラーが常に発生してしまいます。
とりあえずCreateProcessを実行するだけのプログラムを書いてみましたが、これすらも動きません。

コード:

int main(){
	STARTUPINFO si;
	fw::zeromemory(&si);
	si.cb = sizeof(si);

	PROCESS_INFORMATION	pi;

	char cmdline[] = "notepad";
	BOOL result = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
	if(result==0) fw::popup("failed");
	else fw::popup("succeeded!");
	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);
}
※インクルード文等は省略
fw::zeromemory()というのはZeroMemory()の引数を減少させた自作関数で、
fw::popup()というのはポップアップウインドウを表示するための自作関数です。

コンソール画面のスクリーンショットです。
画像

なにがいけないのでしょうか?

OS:Windows8
IDE:VisualStudio2010

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#5

投稿記事 by softya(ソフト屋) » 11年前

基本ですが、とりあえずCreateProcessのエラーコードを調べてみては?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#6

投稿記事 by MoNoQLoREATOR » 11年前

エラーコードを調べてみました。
「メモリ ロケーションへのアクセスが無効です」
とのことです。
無効な場所にアクセスする可能性があるコードには見えないのですが…。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#7

投稿記事 by softya(ソフト屋) » 11年前

zeromemoryにバグがあるんじゃないでしょうか?
私の所では、こうすると動きます。

コード:

#include <windows.h>
#include <stdio.h>

int main() {
	static STARTUPINFO si;
	si.cb = sizeof( si );

	static PROCESS_INFORMATION pi;

	char cmdline[] = "notepad";
	BOOL result = CreateProcess( NULL, cmdline, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi );
	if( result == 0 ) printf( "failed" );
	else printf( "succeeded!" );
	CloseHandle( pi.hThread );
	CloseHandle( pi.hProcess );
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#8

投稿記事 by MoNoQLoREATOR » 11年前

返信ありがとうございます。
siをstaticにすると成功しました。
zeromemoryとpiは特に関係ありませんでした。

コード:

int main(){
	static STARTUPINFO si;
	fw::zeromemory(&si);
	si.cb = sizeof(si);

	PROCESS_INFORMATION	pi;

	char cmdline[] = "notepad";
	BOOL result = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
	if(result==0){
		fw::exerror err;
		printf("\nfailed:%s\n", err.get() );
	}
	else printf("\nsucceeded!\n");
	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);
}
※インクルード文等は省略
※fw::exerrorクラスは拡張エラー情報を管理する自作クラス


とりあえずCreateProcessが使えるようになったので、これから管理クラスの動作テストをしていきます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#9

投稿記事 by softya(ソフト屋) » 11年前

zeromemoryってクリアのサイズをどうやって得ているかかなり疑問なんですが、どうやっているのでしょうか? ポインタしか渡していないように見えますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#10

投稿記事 by MoNoQLoREATOR » 11年前

>>ソフト屋さん
テンプレートを使用して、内部でsizeof演算を行っています。

コード:

template<typename T> void zeromemory(T * req){ ZeroMemory(req, sizeof(T) ); }

というわけで、動作テストを行ってみました。
正常に実行が完了したのですが、結果の文字列を取得することができませんでした。

実行結果のコンソール画面です。
画像

ソースコードです。
► スポイラーを表示
実行したのはfxc.exeという実行ファイルで、パスは通してあります。
これは Microsoft DirectX11 SDK というSDKに含まれている実行ファイルで、シェーダーの情報が別言語で記述されているファイルをC/C++言語用の.hファイルに変換する実行ファイルです。
この実行ファイルをコマンドプロンプトから実行すると、成功・失敗 どちらの場合でもその旨がコンソールに出力されます。
今回はこれを受け取るプログラムを作りたいわけです。

実行が完了しているのに結果がなしというのは有り得ないはずです。
よって、どこかが間違っているということになるはずです。
しかし全くわかりません。
このような場合はどうやってデバッグすれば良いのでしょうか?


ちなみに、充分予想できたと思いますが、fxc.exeはGUIではないため一々ファイル名等を手動で入力する必要があって、これが面倒だからfxc.exeを間接的に実行するGUIソフトを作ろうと思い立ち、現在に至ります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#11

投稿記事 by softya(ソフト屋) » 11年前

>テンプレートを使用して、内部でsizeof演算を行っています。
了解です。
ただ、siをstaticにすると成功するのが意味不明なんですよね。

とりあえず、もっと単純なコードで試すことと、物事を単純にするために自分で作ったコンソールアプリでデバッグすることでしょうか。
他の人の動いているコードを試してみる必要もあるでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: ShellExecute等で実行したプログラムの出力結果を取得したい

#12

投稿記事 by MoNoQLoREATOR » 11年前

解決しました。
CreateProcessの第5引数をtrueにする必要があったようです。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る