たまには、プログラミングなTipsなど。
Windows環境においてたまにアプリケーションから違うコンソールアプリケーション(コマンドラインアプリケーション)呼んだりするのだが(SoundEngineコマンドラインでも呼んでいる)、この時その結果をアプリケーションで取得できるといいなということで。
パイプ
色々調べてみたがどうやらパイプを使ってやるというのが常套手段のようだ。パイプというのはプロセス間通信に使うことができるもので、CreatePipeで作ることができる。パイプをこのCreatePipeで作ると、読み取り側ハンドルと書き込み側ハンドルを得ることができる。ということで、この書き込み側をコンソールアプリケーションに渡して読み込み側でこちらのアプリケーションが読んであげればよいということのようだ。プログラミング(Visual C++)では、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
HANDLE hReadPipe; HANDLE hWritePipe; SECURITY_ATTRIBUTES PipeAttributes; ZeroMemory( &PipeAttributes, sizeof( SECURITY_ATTRIBUTES ) ); PipeAttributes.nLength = sizeof( SECURITY_ATTRIBUTES ); PipeAttributes.bInheritHandle = TRUE; PipeAttributes.lpSecurityDescriptor = NULL; if( !CreatePipe( &hReadPipe, &hWritePipe, &PipeAttributes, 0 ) ) { // 失敗 } |
こんな感じでパイプは完成。bInheritHandleはハンドルの継承ということらしい。このあと、色々とみた例ではDuplicateHandleをしているのだがやらなくても特に問題なく課題を達成できてしまった。結局、DuplicateHandleは何をするのかよくわかっていない、、、要調査。
CreateProcess
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
PROCESS_INFORMATION ProcessInformation; ZeroMemory( &ProcessInformation, sizeof( PROCESS_INFORMATION ) ); STARTUPINFO StartUpInfo; ZeroMemory( &StartUpInfo, sizeof( STARTUPINFO ) ); StartUpInfo.cb = sizeof( STARTUPINFO ); StartUpInfo.dwFlags = STARTF_USESTDHANDLES; StartUpInfo.hStdOutput = hWritePipe; TCHAR pCommandLine[] = _T( "ipconfig" ); if( !CreateProcess ( NULL, pCommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUpInfo, &ProcessInformation ) ) { // 失敗 } |
プロセス起動部分はこんな感じ。StartUpInfo.dwFlags = STARTF_USESTDHANDLES;StartUpInfo.hStdOutput = hWritePipe;とやる標準出力を書き込み用のパイプに設定できるようだ。
ここで、注意点はCreateProcessの第二引数にそのまま、_T( “ipconfig” )などと書いてもコンパイル・ビルドは通ってしまうのだが実行時にエラーが出る。
0x7c82f293 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00415a18 に書き込み中にアクセス違反が発生しました。
こんな感じ。kernel32.dll!7c82f293()というとこでブレイクしているのだが、これがまたさっぱりなのだ。