c ++ - Udfør kommando fra cpp

Indlæg af Hanne Mølgaard Plasc

Problem



Den applikation, jeg arbejder på, skal udføre kommandoer. Kommandoer kan være konsolkommandoer eller 'GUI-applikationer' (som notesblok).


Jeg har brug for at få returkoden i begge tilfælde, og i tilfælde af konsolkommandoer skal jeg også fange output fra stdin og stderr.


For at implementere denne funktion baserede jeg min kode på stakken overløbsproblemet 'Sådan udføres en kommando og får output af kommando inden for C ++ ved hjælp af POSIX?'.


Min kode:


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;
}


Det fungerer perfekt med konsol applikationer, men i tilfælde af 'GUI applikationer' fungerer det ikke som forventet ...


Med 'GUI-applikationer' stopper koden på while (!feof(pipe)) forventer at få noget fra rør.


Jeg forstår, at 'GUI-applikationer' som notesblok ikke er færdige, indtil nogen interagerer med dem (bruger lukker appen, dræber processen osv.),
men når jeg starter konsolprogrammer fra Windows Console, kommer du straks tilbage.
Jeg vil gerne få den samme adfærd fra 'GUI-applikationer' ...


En mulig løsning ville være at tilføje variablen isGui, der angiver, hvornår koden skal læses fra røret, men jeg afviste denne indstilling, da jeg ikke vil angive, om det er en 'GUI-applikation' eller ej.

Bedste reference


Nå skal du ikke angive isGui dig selv, men opdage det ved at kontrollere delsystemet af den eksekverbare (windows/konsol) inden udførelsen af ​​kommandoen, og i tilfælde af windows springe venter på de omdirigerede rør.


For eksempel bruger SHGetFileInfo med SHGFI\_EXETYPE flag: [10]


bool isGuiApplication(const std::string& command)
{
  auto it = command.find\_first\_of(" 	");
  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
";
  }
  return ((uintptr\_t)exetype & 0xffff0000);
}


Så senere i koden ...


  if (isGuiApplication(command)) {
    cout << "GUI application
";
    system(command.c\_str()); // don't wait on stdin
  }
  else {
    cout << "Console application
";
    . . .
    // \_popen and stuff
  }