Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows可执行包装的CreateProcess用法?_Windows_Visual C++_Createprocess - Fatal编程技术网

Windows可执行包装的CreateProcess用法?

Windows可执行包装的CreateProcess用法?,windows,visual-c++,createprocess,Windows,Visual C++,Createprocess,TL;博士: CreateProcess(?、、?、…)用于: 通过当前过程参数(即) 正确连接标准DIN和标准输出 创建标志 我有以下问题: 我需要使用自定义环境和自定义参数启动给定的第三方可执行文件。(均为半固定式) 我不能使用批处理文件,因为调用模块的(第三方)端直接调用CreateProcess 我需要传递任何通过的附加参数 所以,我想做的是创建一个非常简单的可执行启动器,它相当于一个批处理文件,如: set PATH=... set WHATEVER=... ...\3rd-

TL;博士

CreateProcess(?、、?、…)
用于:

  • 通过当前过程参数(即)
  • 正确连接标准DIN和标准输出
  • 创建标志

我有以下问题:

  • 我需要使用自定义环境和自定义参数启动给定的第三方可执行文件。(均为半固定式)
  • 我不能使用批处理文件,因为调用模块的(第三方)端直接调用
    CreateProcess
  • 我需要传递任何通过的附加参数
所以,我想做的是创建一个非常简单的可执行启动器,它相当于一个批处理文件,如:

set PATH=...
set WHATEVER=...
...\3rd-pty-tool.exe -switch1 -switch2 %*
exit /B %ERRORLEVEL%
我当然不想把东西弄乱——反正我有VisualStudio的时候太难看了

原则上运行另一个:

通过via等人为子进程设置环境也很容易

然而,对我来说并不微不足道的是要传递给什么:

  • 如何获得当前Win32进程的
    %*
    等效值
  • 只传递
    lpApplicationName
    ,只传递
    lpCommandLine
    还是同时传递两者
  • 如何处理继承和创建标志
  • 如何正确转发/返回标准输入和标准输出


不是傻瓜:

应该相当简单

BOOL WINAPI CreateProcess(
  _In_opt_    LPCTSTR               lpApplicationName,
  _Inout_opt_ LPTSTR                lpCommandLine,
  _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_        BOOL                  bInheritHandles,
  _In_        DWORD                 dwCreationFlags,
  _In_opt_    LPVOID                lpEnvironment,
  _In_opt_    LPCTSTR               lpCurrentDirectory,
  _In_        LPSTARTUPINFO         lpStartupInfo,
  _Out_       LPPROCESS_INFORMATION lpProcessInformation
);
让我们把它整理一下

  • lpApplicationName
    -如果您有要运行的可执行文件的完整路径,请将其放在此处。这样可以确保获得预期的可执行文件,即使路径上有另一个同名的可执行文件

  • lpCommandLine
    -第一个元素是可执行文件名。如果指定了
    lpApplicationName
    ,则不需要完全限定,甚至不需要是可执行文件的实际名称,但它确实需要存在。这必须是可写缓冲区,不能是常量字符串

如果您的额外参数可以放在命令行的末尾,这很容易:

wchar_t buffer[1024];
wcscpy_s(buffer, _countof(buffer), GetCommandLine());
wcscat_s(buffer, _countof(buffer), L" -switch1 -switch2");
否则,您需要解析命令行以找到插入参数的正确位置,如下所示:

while (*lpCmdLine == L' ') lpCmdLine++;
while (ch = *lpCmdLine) 
{
    if (ch == L'"') for (lpCmdLine++; ch = *lpCmdLine; lpCmdLine++) if (ch == L'"') break;
    if (ch == L' ') break;
    lpCmdLine++;
}
while (*lpCmdLine == L' ') lpCmdLine++;
  • lpProcessAttributes
    lpThreadAttributes
    -
    NULL

  • bInheritHandles
    -
    TRUE
    ,因为您希望子对象继承标准句柄

  • dwCreationFlags
    -您的场景中不需要任何标志,因此
    0

  • lpEnvironment
    -
    NULL
    传递当前环境。在某些情况下,您可能希望显式地构造一个新环境,或者环境的一个修改副本,但由于您的进程只存在于启动子进程,因此不需要这样做

  • lpCurrentDirectory
    -
    NULL
    继承当前目录

  • lpStartupInfo
    -调用
    GetStartupInfo
    以使用与当前流程相同的设置填写此文件,或者将其保留为空,就像您发布的代码一样

  • lpProcessInformation
    -这是一个输出参数,如代码所示。在您的场景中,当一个应用程序替代另一个应用程序时,您可能希望保留进程句柄,并使用它等待子进程退出,然后再退出自己。(如果您知道,如果您在孩子之前退出,您的父母不会感到困惑,那么这是没有必要的。)


除了确保设置了
bInheritHandles
之外,您不需要对标准句柄做任何特殊的处理。默认情况下,子级保留与父级相同的标准句柄。

我不知道
%*
是什么意思,但您可能也在寻找感兴趣的内容:@Igor
%*
作为批处理文件。&谢谢,那篇重定向文章很好。谢谢Harry。很好的总结!实际上,我当前的测试应用程序设置了
bInhertHandles:=FALSE
,它仍然可以工作。涉及的两个二进制文件都是“控制台可执行文件”。在这种情况下,似乎不需要句柄继承。我打算在我有了完整的例子后再举出来。是的,我决定不讨论这个问题,因为这是一个不必要的复杂问题。在Windows7及更早版本中,如果标准句柄仍然指向原始控制台句柄,则不需要句柄继承。这是因为它们不是真正的内核句柄,它们是“psuedohandles”。如果标准句柄被重定向到文件或管道,我认为如果没有句柄继承,它将无法工作,尽管我没有检查。另外,如果我理解正确的话,在较新版本的Windows控制台中,句柄是真正的内核句柄。Windows可能会在这两种情况下都出现特殊情况,但为了确保最大的兼容性,我建议在此场景中启用继承。(对于更复杂的场景,有一个选项可以精确指定继承哪些句柄,这可能是一般情况下的最佳选择。)
wchar_t buffer[1024];
wcscpy_s(buffer, _countof(buffer), GetCommandLine());
wcscat_s(buffer, _countof(buffer), L" -switch1 -switch2");
while (*lpCmdLine == L' ') lpCmdLine++;
while (ch = *lpCmdLine) 
{
    if (ch == L'"') for (lpCmdLine++; ch = *lpCmdLine; lpCmdLine++) if (ch == L'"') break;
    if (ch == L' ') break;
    lpCmdLine++;
}
while (*lpCmdLine == L' ') lpCmdLine++;