c++ - 具有 2 个重定向管道的 CreateProcess 返回退出代码 1
问题描述
我是 WIN32 API 的新手,可以使用一些帮助来确定我的代码中缺少什么。我的目标是运行批处理脚本(或 PowerShell 脚本),等待完成,然后在完成后获取 stdout / stderr。
按照这个和msdn 上的这篇文章,关于创建进程并将 stdout 和 stderr 重定向到句柄。我将这些样本混合在一起,并提出了以下代码:
int execute_commnad(std::string& command,std::string& output,int& timeout_seconds) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD return_code = NULL;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si,sizeof(si));
si.cb = sizeof(si);
si.hStdOutput = child_stdout_handle;
si.hStdError = child_stdout_handle;
si.dwFlags |= STARTF_USESTDHANDLES;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Connect Child stdout to parent_stdout_handle
if (!CreatePipe(&parent_stdout_handle,&child_stdout_handle,&saAttr,0))
{
output = "Could not create stdout pipe. Error: " + std::to_string(GetLastError());
close_handles();
return -1;
}
if (! SetHandleInformation(parent_stdout_handle,HANDLE_FLAG_INHERIT,0))
{
output = "Could not set handle information for stdout pipe. Error: " + std::to_string(GetLastError());
close_handles();
return -1;
}
// Create Process
if (!CreateProcess(NULL,LPSTR(command.c_str()),NULL,NULL,TRUE,0,NULL,NULL,&si,&pi)) {
output = "Failed to create process. Error: " + std::to_string(GetLastError());
close_handles();
return -1;
}
CloseHandle(child_stdout_handle);
// Wait for process to finish or timeout
if (timeout_seconds == NULL) {
WaitForSingleObject(pi.hProcess,INFINITE);
}
else {
WaitForSingleObject(pi.hProcess,DWORD(timeout_seconds * 1000));
}
if (!GetExitCodeProcess(pi.hProcess,&return_code)) {
output = "Failed to fetch exit code";
close_handles();
return -1;
}
if (STILL_ACTIVE == return_code) {
TerminateProcess(sub_process,return_code);
output = "Command did not finish within defined timeout threshold";
}
else if (STATUS_PENDING == return_code) {
output = "process is pending";
}
else {
DWORD dwRead;
CHAR chBuf[4096];
BOOL bSuccess = FALSE;
for (;;) {
bSuccess = ReadFile(parent_stdout_handle,chBuf,4096,&dwRead,NULL);
if (! bSuccess || dwRead == 0) break;
output = *reinterpret_cast<std::string*>(parent_stdout_handle);
}
}
close_handles();
return 0;
};
void close_handles(void) {
CloseHandle(parent_stdout_handle);
CloseHandle(child_stdout_handle);
CloseHandle(sub_process);
};
在执行上面的函数之前,我使用std::ofstream
包含“echo hello”创建了 .bat 文件,并将文件的 FQN 保存到名为的变量中file_name
并运行以下代码:
int rc = 0;
std::string cmd = "cmd.exe /c " + file_name + " " + script_params;
rc = execute_commnad(cmd,this->output,timeout_in_seconds);
调试时,这些是我得到的值GetExitCodeProcess
:
- cmd: cmd.exe /c "O:\\Programming\\cpp\...\\script_file.bat" 1 2 3
- 返回代码:1
我尝试用cmd.exe
FQN 替换,但结果相同,尝试运行一些简单的东西,但cmd.exe /c "echo hello"
仍然返回 return_code 1。
过去两天我一直在努力寻找原因,但无济于事。
除了无效的代码(性能方面)之外,是否有人对可能出现的问题提出建议?
提前致谢!
解决方案
确保child_stdout_handle
在将句柄传递给CreateProcess
.
此外,您需要打印chBuf
您读入的值ReadFile
,而不是parent_stdout_handle
. 将文件句柄转换string
为没有意义,您可以尝试:
for (;;) {
bSuccess = ReadFile(parent_stdout_handle, chBuf, 4096, &dwRead, NULL);
if (!bSuccess || dwRead == 0) break;
chBuf[dwRead] = '\0';
output += chBuf;
}
cout << output << endl;
推荐阅读
- mysql - 我尝试加入两个表,但另一个表名在第一个表的列中。可以加入还是有
- sql-server - 无法加载文件或程序集“Microsoft.AnalysisServices.AdomdClientUI”
- excel - 图片周围的VBA Excel边框
- python - 用于计算增值税回报的 TKinter 程序“不能将序列乘以“浮点”类型的非整数
- python - 使用 MySQL 容器对 Django 应用程序进行 Dockerize
- c++ - 如何使用算法将十进制数转换为二进制数
- css - 如何调整我的垫子的高度,使其填充剩余的垂直空间并且任何多余的部分都是可滚动的?
- scrapy - 爬取时迭代返回相同的结果
- mysql - 在许多 UPDATE / INSERT 操作之后,MySQL (5.7) 索引是否需要一段时间才能更新?
- mysql - 如何将密码作为 ssh sql 命令的参数