◆ 名前なしパイプのサンプルプログラム
//------------------------------------------------------------------------------
// module name: pipe.cpp
// desc: 名前なしパイプのサンプルプログラム
//
// 参考URL <http://support.microsoft.com/support/kb/articles/q190/3/51.asp>
//------------------------------------------------------------------------------
#include <windows.h>
#include <conio.h> // getch()
#include <iostream> // std::cout, std::endl
// 子プロセスの標準出力を読み取る
void read_child_stdout(HANDLE h_stdout_r);
//------------------------------------------------------------------------------
// name: main()
// desc: 子プロセス c:\aaa\bbb\ccc\test.exe の標準出力を、名前なしパイプを用いて
// 親プロセスにリダイレクトする
//------------------------------------------------------------------------------
int main()
{
char* curr_dir = "c:\\aaa\\bbb\\ccc"; // 子プロセスの実行時カレントディレクトリ
char* cl = "c:\\aaa\\bbb\\ccc\\test"; // コマンドライン
// 標準出力パイプ
HANDLE h_stdout_r, h_stdout_r_tmp; // 標準出力を読み込むパイプ端 (親側)
HANDLE h_stdout_w; // 標準出力へ書き込むパイプ端 (子側)
// 標準入力パイプ
HANDLE h_stdin_w, h_stdin_w_tmp; // 標準入力へ書き込むパイプ端 (親側)
HANDLE h_stdin_r; // 標準入力を読み込むパイプ端 (子側)
// 標準エラー出力パイプ
HANDLE h_stderr_w; // 標準エラー出力へ書き込むパイプ端 (子側)
HANDLE h_parent_process = GetCurrentProcess(); // 親プロセス(カレントプロセス)のハンドル
HANDLE h_child_process; // 子プロセスのハンドル
// Setup SECURITY_ATTRIBUTES structure
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// ----------------( h_stdout_w )----------------
// Create the child output pipe.
CreatePipe(&h_stdout_r_tmp, &h_stdout_w, &sa, 0);
// ----------------( h_stderr_w )----------------
// Create a duplicate of the output write handle for the std error
// write handle. This is necessary in case the child application
// closes one of its std output handles.
DuplicateHandle(h_parent_process, h_stdout_w, h_parent_process, &h_stderr_w, 0, TRUE, DUPLICATE_SAME_ACCESS);
// ----------------( h_stdin_r )----------------
// Create the child input pipe.
CreatePipe(&h_stdin_r, &h_stdin_w_tmp, &sa, 0);
// ----------------( h_stdout_r, h_stdin_w )----------------
// Create new output read handle and the input write handles. Set
// the Properties to FALSE. Otherwise, the child inherits the
// properties and, as a result, non-closeable handles to the pipes
// are created. ↓ Uninheritable
DuplicateHandle(h_parent_process, h_stdout_r_tmp, h_parent_process, &h_stdout_r, 0, FALSE, DUPLICATE_SAME_ACCESS);
DuplicateHandle(h_parent_process, h_stdin_w_tmp, h_parent_process, &h_stdin_w, 0, FALSE, DUPLICATE_SAME_ACCESS);
// Close inheritable copies of the handles you do not want to be inherited.
CloseHandle(h_stdout_r_tmp);
CloseHandle(h_stdin_w_tmp);
// Setup the STARTUPINFO structure.
STARTUPINFO si;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdOutput = h_stdout_w;
si.hStdInput = h_stdin_r;
si.hStdError = h_stderr_w;
// 子プロセスを起動する
PROCESS_INFORMATION pi;
CreateProcess(NULL, cl, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, curr_dir, &si, &pi);
// Set child process handle to cause threads to exit.
h_child_process = pi.hProcess;
// Close any unnecessary handles.
CloseHandle(pi.hThread);
// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
CloseHandle(h_stdout_w);
CloseHandle(h_stdin_r);
CloseHandle(h_stderr_w);
// 子プロセスの標準出力を読み取る
read_child_stdout(h_stdout_r);
// 後始末 (パイプと子プロセスを閉じる)
CloseHandle(h_stdout_r);
CloseHandle(h_stdin_w);
CloseHandle(h_child_process);
std::cout << "\n\n\nHit any key to exit." << std::endl;
getch();
return 0;
}
//------------------------------------------------------------------------------
// name: read_child_stdout()
// desc: 子プロセスの標準出力を読み取る
//------------------------------------------------------------------------------
void read_child_stdout(HANDLE h_stdout_r)
{
char buf[256]; // 読み取りバッファ
DWORD bytes; // 実際に読み取ったデータのサイズ
while (ReadFile(h_stdout_r, buf, sizeof(buf), &bytes, NULL)) {
int len = bytes / sizeof(char);
buf[len] = '\0';
std::cout << buf;
}
std::cout << std::endl;
}