我正在处理的应用程序需要执行命令。命令可以是控制台命令或GUI应用程序' (比如记事本)。
我需要在两种情况下获取返回代码,在控制台命令的情况下,我还需要捕获stdin和stderr的输出。
为了实现此功能,我将代码基于堆栈溢出问题'How to execute a command and get output of command within C++ using POSIX?'。
我的代码:
int ExecuteCmdEx(const char* cmd, std::string &result)
{
char buffer[128];
int retCode = -1; // -1 if error ocurs.
std::string command(cmd);
command.append(" 2>&1"); // also redirect stderr to stdout
result = "";
FILE* pipe = _popen(command.c_str(), "r");
if (pipe != NULL) {
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
}
catch (...) {
retCode = _pclose(pipe);
throw;
}
retCode = _pclose(pipe);
}
return retCode;
}
它与控制台应用程序完美配合,但在GUI应用程序的情况下'它没有按预期工作......
使用' GUI应用程序',while (!feof(pipe))
上的代码会停止从管道中获取内容。
我理解' GUI应用程序'像记事本一样,直到有人与他们互动(用户关闭应用程序,杀死进程等), 但是当我从Windows控制台启动控制台应用程序时,会立即提示。 我想从GUI应用程序' ...
中获得相同的行为一种可能的解决方案是添加isGui
变量,指示代码何时应该从管道读取,但我拒绝了此选项,因为我不想表明它是否是&#39 ; GUI应用程序'或不。
答案 0 :(得分:0)
那么你不必自己指示 isGui
,而是在执行之前通过检查可执行文件的子系统(windows / console)来检测它命令,如果窗口跳过等待重定向的管道。
例如,使用带有SHGFI_EXETYPE
标记的SHGetFileInfo
:
bool isGuiApplication(const std::string& command)
{
auto it = command.find_first_of(" \t");
const std::string& executable = (it == std::string::npos ? command : command.substr(0, it));
DWORD_PTR exetype = SHGetFileInfo(executable.c_str(), 0, nullptr, 0, SHGFI_EXETYPE);
if (!exetype) {
cerr << "Executable check failed\n";
}
return ((uintptr_t)exetype & 0xffff0000);
}
然后在代码中......
if (isGuiApplication(command)) {
cout << "GUI application\n";
system(command.c_str()); // don't wait on stdin
}
else {
cout << "Console application\n";
. . .
// _popen and stuff
}