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