从cpp执行命令

时间:2017-10-27 08:48:53

标签: c++ windows

我正在处理的应用程序需要执行命令。命令可以是控制台命令或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应用程序'或不。

1 个答案:

答案 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
  }