执行流程并在 Windows 上获得结果
Execute process and get result on Windows
我有一段代码可以执行一个过程并检索结果。
namespace {
FILE* really_popen(const char* cmd, const char* mode) {
#ifdef _MSC_VER
return _popen(cmd, mode);
#else
return popen(cmd, mode);
#endif
}
void really_pclose(FILE* pipe) {
#ifdef _MSC_VER
_pclose(pipe);
#else
pclose(pipe);
#endif
}
std::string ExecuteProcess(std::string cmd) {
FILE* pipe = really_popen(cmd.c_str(), "r");
if (!pipe) throw std::runtime_error("Could not invoke command " + cmd);
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
really_pclose(pipe);
return result;
}
}
这对我来说在 Linux 上工作得很好,但在 Windows 上它有一个可怕的死锁习惯——似乎 fgets
从来没有 returns。我查看了 CRT 资源,fgets
最终委托给了 ReadFile
,但从未 returns.
如果我从命令行调用命令,它 returns 一秒钟之内。
如何在不使父进程死锁的情况下读取 Windows 上的输出?
如果 child 尚未退出,则对 fgets() 的调用将不会退出,因此您需要解决 child 未退出的原因。这种情况最可能的原因是 child 挂起,因为它没有标准输入。
如果这是问题所在,您可以通过将管道模式更改为 "rw" 来解决它。您通常不需要对额外的管道做任何事情,它只需要在那里。
(正如您在评论中提到的,问题也可以通过使用命令 shell 重定向来为 child 提供 NUL
作为标准输入的句柄来解决。)
我有一段代码可以执行一个过程并检索结果。
namespace {
FILE* really_popen(const char* cmd, const char* mode) {
#ifdef _MSC_VER
return _popen(cmd, mode);
#else
return popen(cmd, mode);
#endif
}
void really_pclose(FILE* pipe) {
#ifdef _MSC_VER
_pclose(pipe);
#else
pclose(pipe);
#endif
}
std::string ExecuteProcess(std::string cmd) {
FILE* pipe = really_popen(cmd.c_str(), "r");
if (!pipe) throw std::runtime_error("Could not invoke command " + cmd);
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
really_pclose(pipe);
return result;
}
}
这对我来说在 Linux 上工作得很好,但在 Windows 上它有一个可怕的死锁习惯——似乎 fgets
从来没有 returns。我查看了 CRT 资源,fgets
最终委托给了 ReadFile
,但从未 returns.
如果我从命令行调用命令,它 returns 一秒钟之内。
如何在不使父进程死锁的情况下读取 Windows 上的输出?
如果 child 尚未退出,则对 fgets() 的调用将不会退出,因此您需要解决 child 未退出的原因。这种情况最可能的原因是 child 挂起,因为它没有标准输入。
如果这是问题所在,您可以通过将管道模式更改为 "rw" 来解决它。您通常不需要对额外的管道做任何事情,它只需要在那里。
(正如您在评论中提到的,问题也可以通过使用命令 shell 重定向来为 child 提供 NUL
作为标准输入的句柄来解决。)