
用 CreateProcess 启动 EXE 并同步等待退出
这是 Windows 下最可控的方式,能捕获进程句柄、设定启动参数、控制窗口行为,且可准确等待子进程结束。CreateProcess 不经过 shell,避免了空格路径或特殊字符被错误解析的问题。
关键点:
-
CreateProcess的第一个参数(lpApplicationName)建议设为nullptr,把完整路径和参数都塞进第二个参数(lpCommandLine),否则路径含空格时极易失败 - 必须用
WaitForSingleObject(hProcess, INFINITE)等待,不能只调CloseHandle - 获取退出码要用
GetExitCodeProcess(hProcess, &exitCode),不是直接返回值
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
if (CreateProcess(nullptr, "C:\\tools\\mytool.exe -v --input data.txt", nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitCode = 0;
GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
system() 看似简单但隐患多
system() 本质是调用 cmd.exe /c,所有命令都经 shell 解析——这意味着路径空格、重定向符 >、管道 | 都可能被意外触发,且无法获取真实退出码(Windows 下它只返回 cmd.exe 的状态,不是目标程序的)。
仅适合调试或执行极简命令,例如:system("pause") 或 system("notepad.exe")。一旦涉及参数、路径或需判断成败,就该换掉。
立即学习“C++免费学习笔记(深入)”;
- 路径含空格时,
system("C:\Program Files\tool.exe")会失败,必须手动加双引号:`system("\"C:\\Program Files\\tool.exe\"")` - 无法设置工作目录、隐藏窗口、继承句柄等
- 在服务或无桌面会话中可能卡死(
cmd.exe等待交互)
需要传参、设工作目录或隐藏窗口?只能用 CreateProcess
system() 完全不支持这些需求;而 CreateProcess 通过 STARTUPINFO 和 CREATE_NO_WINDOW 等标志可精细控制。
- 设工作目录:填
lpCurrentDirectory参数,如"C:\\data" - 隐藏子窗口:在
dwCreationFlags中加CREATE_NO_WINDOW(适用于控制台工具不想弹黑窗) - 重定向 stdin/stdout:需先用
CreatePipe创建句柄,再填入STARTUPINFO.hStdXXX,并设STARTF_USESTDHANDLES
注意:CREATE_NO_WINDOW 对 GUI 程序无效,对控制台程序才起作用;若目标本身是 GUI,它本来就不会显示控制台窗口。
跨平台?别指望 CreateProcess 或 system 直接移植
CreateProcess 是 Windows API,Linux/macOS 下不存在;system() 虽然 POSIX 有定义,但行为差异大:Linux 下它调 /bin/sh -c,同样有 shell 注入风险,且无法可靠获取子进程 PID 或等待精确退出。
如果真要跨平台,得封装一层:
- Windows 路径用
CreateProcess - Linux/macOS 用
fork()+execv()+waitpid() - 或者用 C++17 的
std::process(尚未标准化)或第三方库如boost::process
硬写 #ifdef _WIN32 分支比强行统一接口更实际,尤其当项目只跑 Windows 时。










