CreateProcessを使用して_hg > test.txt
_のような単純なコマンドを実行してみました。 (アプリケーション名とそのパラメーターに分離するのではなく)文字列全体を実行してみました。 CreateProcess(0, "notepad.exe test.txt", ...)
が機能するのにCreateProcess(0, "hg > test.txt", ...)
が機能しないのはなぜですか?
CreateProcess
に渡されるコマンドラインでstdoutリダイレクトを使用することはできません。 stdoutをリダイレクトするには、出力用のファイルハンドルを STARTUPINFO
構造で指定する必要があります。
また、別の、より微妙な、間違いを犯しています。 lpCommandLine
はバッファを上書きするため、2番目のパラメータCreateProcess
は書き込み可能なメモリを指す必要があります。関数のANSIバージョンをたまたま使用している場合は、これを回避できますが、Unicodeバージョンではできません。
この関数のUnicodeバージョンCreateProcessWは、この文字列の内容を変更できます。したがって、このパラメーターを読み取り専用メモリへのポインター(const変数やリテラル文字列など)にすることはできません。このパラメーターが定数文字列の場合、関数はアクセス違反を引き起こす可能性があります。
以下のコードは、stdoutとstderrが指定されたファイルにリダイレクトされたコンソールレスプロセスを作成します。
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE h = CreateFile(_T("out.log"),
FILE_APPEND_DATA,
FILE_SHARE_WRITE | FILE_SHARE_READ,
&sa,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL ret = FALSE;
DWORD flags = CREATE_NO_WINDOW;
ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si, sizeof(STARTUPINFO) );
si.cb = sizeof(STARTUPINFO);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = NULL;
si.hStdError = h;
si.hStdOutput = h;
TCHAR cmd[]= TEXT("Test.exe 30");
ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
if ( ret )
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
return -1;
}
Microsoftには、標準出力をリダイレクトする方法の例があります: http://msdn.Microsoft.com/en-us/library/ms682499(VS.85).aspx 。
CreateProcess()はプロセスを起動しますが、コマンドラインitnerpreterではありません。 ">"が何であるかを認識していないため、ストリームのリダイレクトは行われません。ファイルtest.txtを自分で開き、そのハンドルをSTARTUPINFO構造内のCreateProcessに渡す必要があります。 CreateProcess[〜#〜] startupinfo [〜#〜]