将 CreateProcess 输入流重定向到文件

Posted

技术标签:

【中文标题】将 CreateProcess 输入流重定向到文件【英文标题】:Redirecting CreateProcess input stream to a file 【发布时间】:2017-08-25 09:16:14 【问题描述】:

我正在使用 CreateProcess 替换我的代码中的 system() 调用。我正在使用:

system(xfoil.exe < create_results.txt");

我用这个代替:

PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter

LPCWSTR input_file = _tcsdup(TEXT(".\\create_results.txt"));

HANDLE inpfl = CreateFile(input_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
StartupInfo.hStdInput = inpfl;

ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo; //Only compulsory field
LPCWSTR exe_path =_tcsdup(TEXT(".\\xfoil.exe"));

if (CreateProcess(exe_path, NULL,
    NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL,
    NULL, &StartupInfo, &ProcessInfo))

    WaitForSingleObject(&ProcessInfo.hProcess, 2000);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(inpfl);


else

    CloseHandle(inpfl);
    std::cout << "Could not create xfoil process" << std::endl;

原因是我需要控制允许进程运行多长时间(在这种情况下为 2000 毫秒),但是这种方法似乎不起作用。 我将进程的输入重定向到我想要作为输入的文件的句柄(以替换

【问题讨论】:

订单很重要!你在哪里设置hStdInput,你在哪里调用ZeroMemory 你需要调用 ZeroMemory BEFORE 你分配给 hStdInput vtc 为“简单的印刷错误” 该死,这是一个菜鸟的错误。我已更改顺序,但仍无法按预期工作。 文件正确打开了吗? 【参考方案1】:

您需要设置文件安全属性以允许继承句柄和启动信息标志以使子进程使用传递的句柄:

::STARTUPINFO startup_information;

::SECURITY_ATTRIBUTES security_attributes

    sizeof(::SECURITY_ATTRIBUTES)
,   nullptr
,   TRUE // allow handle to be inherited
;

::HANDLE const inpfl::CreateFileW(input_file, GENERIC_READ, FILE_SHARE_READ, ::std::addressof(security_attributes), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == inpfl)

    auto const last_error::GetLastError();
    // handle error...


startup_information.cb = sizeof(startup_information);
startup_information.dwFlags = STARTF_USESTDHANDLES;
startup_information.hStdInput = inpfl;

【讨论】:

为了完整起见,您应该提到原始代码中存在两个错误:未设置dwFlags,以及分配ZeroMemory后调用hStdInput。跨度> @MartinBonner 实际上是三个错误:为安全属性提供空指针会使句柄不可继承,因此子进程将无法使用它。反正我猜 op 已经知道ZeroMemory 了。 我正在尝试这个解决方案,看起来绝对是正确的方向。 ZeroMemory 是一个我没有立即注意到的愚蠢错误。不知道标志和安全属性。 它似乎工作正常,我确实得到一些文件被另一个进程错误打开,但我会在没有太多问题的情况下解决这个问题,谢谢。从中学到了很多。 如果创建(父)进程是一个控制台进程,那么STARTUPINFO 标准句柄就必须被使用。例如,cmd.exe 从不使用它们。在这种情况下,当前的标准句柄(即通过SetStdHandle 设置)由子控制台进程继承,无论它们是否可继承或子进程是否是通过继承创建的。非控制台子进程也在其标准句柄中继承句柄 values,但实际上继承句柄要求它们是可继承的,并创建具有继承的进程,而 cmd.exe 始终使用这一点。【参考方案2】:
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter

LPCWSTR input_file = _tcsdup(TEXT(".\\create_results.txt"));

HANDLE inpfl = CreateFile(input_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
StartupInfo.hStdInput = inpfl;

下次调用后 StartupInfo.hStdInput 会发生什么?

ZeroMemory(&StartupInfo, sizeof(StartupInfo));

糟糕... hStdInput 现在归零了

最初这样做...

PROCESS_INFORMATION ProcessInfo = ;
STARTUPINFO StartupInfo = ;

... 将防止您需要将任何东西归零...see

另外,根据 CreateProcess StartupInfo documentation,您必须为 hStdInput 设置 dwFlags STARTF_USESTDHANDLES,否则默认输入是键盘缓冲区

【讨论】:

以上是关于将 CreateProcess 输入流重定向到文件的主要内容,如果未能解决你的问题,请参考以下文章

Java 演示如何用标准的输入输出流重定向到一个文件

将输出流以外的两个或多个 Powershell 流重定向到同一个文件

25 Java学习之标准I/O流重定向

纠正流重定向中的乱序打印

C语言编程: CreateProcess标准输出重定向到文件

将输入传递给由 CreateProcess() 创建的进程