如何使用CreateProcess将输出重定向到文件?

Pau*_*nta 24 c c++ winapi io-redirection

我尝试使用CreateProcess来运行一个简单的命令hg > test.txt.我尝试将字符串作为一个整体运行(而不是将其分成应用程序名称及其参数).为什么CreateProcess(0, "notepad.exe test.txt", ...)工作但CreateProcess(0, "hg > test.txt", ...)不工作?

小智 24

下面的代码创建了一个无控制台的进程,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;
}
Run Code Online (Sandbox Code Playgroud)

  • 代码旁边的描述会很方便.至少评论 (3认同)
  • 可能会错过生成子进程后文件的 CloseHandle()。 (2认同)
  • 顺便说一句,如果您使用 STARTF_USESTDHANDLES 并且不想重定向其中一个句柄,您可以执行以下操作: si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); (2认同)

Dav*_*nan 23

您不能在传递给的命令行中使用stdout重定向CreateProcess.要重定向stdout,您需要为STARTUPINFO结构中的输出指定文件句柄.

你也犯了另一个更微妙的错误.第二个参数lpCommandLine必须指向可写内存,因为它会CreateProcess覆盖缓冲区.如果您碰巧使用该函数的ANSI版本,那么您将逃避这一点,但不适用于Unicode版本.

此函数的Unicode版本CreateProcessW可以修改此字符串的内容.因此,此参数不能是只读内存的指针(例如const变量或文字字符串).如果此参数是常量字符串,则该函数可能会导致访问冲突.

  • 为了好奇你为什么需要传入一个可写缓冲区:[为什么`CreateProcess`函数修改它的输入命令行?](http://blogs.msdn.com/b/oldnewthing/archive/2009/06/ 01/9673254.aspx) (14认同)

Tam*_*jen 8

Microsoft有一个示例如何重定向标准输出:http: //msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx.

  • 是的,那种工作,但请记住,该示例中存在一个错误,阻止`ReadFromPipe`退出.在调用该函数之前,需要调用:`CloseHandle(g_hChildStd_OUT_Wr);`.此外,您可能希望在关闭句柄之前等待子进程退出,例如:`WaitForSingleObject(piProcInfo.hProcess,INFINITE);`. (8认同)

MK.*_*MK. 7

CreateProcess()启动进程,它不是命令行itnerpreter.它不知道">"是什么,也不会为你做流重定向.您需要自己打开文件test.txt并将其传递给STARTUPINFO结构中的CreateProcess : CreateProcess STARTUPINFO