web-dev-qa-db-ja.com

CreateProcessで出力をファイルにリダイレクトするにはどうすればよいですか?

CreateProcessを使用して_hg > test.txt_のような単純なコマンドを実行してみました。 (アプリケーション名とそのパラメーターに分離するのではなく)文字列全体を実行してみました。 CreateProcess(0, "notepad.exe test.txt", ...)が機能するのにCreateProcess(0, "hg > test.txt", ...)が機能しないのはなぜですか?

25
Paul Manta

CreateProcess に渡されるコマンドラインでstdoutリダイレクトを使用することはできません。 stdoutをリダイレクトするには、出力用のファイルハンドルを STARTUPINFO 構造で指定する必要があります。

また、別の、より微妙な、間違いを犯しています。 lpCommandLineはバッファを上書きするため、2番目のパラメータCreateProcessは書き込み可能なメモリを指す必要があります。関数のANSIバージョンをたまたま使用している場合は、これを回避できますが、Unicodeバージョンではできません。

この関数のUnicodeバージョンCreateProcessWは、この文字列の内容を変更できます。したがって、このパラメーターを読み取り専用メモリへのポインター(const変数やリテラル文字列など)にすることはできません。このパラメーターが定数文字列の場合、関数はアクセス違反を引き起こす可能性があります。

23
David Heffernan

以下のコードは、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;
}
24
Lukas Koblovsky

Microsoftには、標準出力をリダイレクトする方法の例があります: http://msdn.Microsoft.com/en-us/library/ms682499(VS.85).aspx

8
Tamas Demjen

CreateProcess()はプロセスを起動しますが、コマンドラインitnerpreterではありません。 ">"が何であるかを認識していないため、ストリームのリダイレクトは行われません。ファイルtest.txtを自分で開き、そのハンドルをSTARTUPINFO構造内のCreateProcessに渡す必要があります。 CreateProcess[〜#〜] startupinfo [〜#〜]

7
MK.