>

작업중인 응용 프로그램에서 명령을 실행해야합니다. 명령은 콘솔 명령 또는 'GUI 응용 프로그램'(예 : 메모장) 일 수 있습니다.

두 경우 모두에 리턴 코드를 가져와야하며 콘솔 명령의 경우 stdin 및 stderr의 출력도 잡아야합니다.

이 기능을 구현하기 위해 스택 오버플로 질문 'POSIX를 사용하여 C ++에서 명령을 실행하고 명령을 출력하는 방법은 무엇입니까?'.

내 코드 :

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 를 추가하는 것입니다.  코드가 파이프에서 코드를 읽어야하는시기를 나타내는 변수이지만 'GUI 응용 프로그램'인지 여부를 표시하고 싶지 않으므로이 옵션을 거부했습니다.


  • 답변 # 1

    글쎄, isGui표시할 필요는 없습니다.  명령을 실행하기 전에 실행 파일 (Windows/콘솔)의 하위 시스템을 확인하고 리디렉션 된 파이프에서 대기하는 창을 건너 뛰는 경우 자신을감지합니다.

    예를 들어, SHGetFileInfo 사용   SHGFI_EXETYPE 와 함께  플래그 :

    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
      }
    
    

관련 자료

  • 이전 c++ - 0 리터럴을 전달할 때 포인터와 참조 사이의 과부하 선택에 대한 이중 인수
  • 다음 hbase - 피닉스에 여러 열 삽입 - python