Arhn - архитектура программирования

Команда C++ popen без консоли

когда я использую popen для получения вывода команды, скажем, dir, она вызывает консоль.

однако можно ли получить вывод команды без появления консоли?

Я использую Visual C++ и хочу создать библиотеку для возврата вывода какой-либо команды, скажем, dir.

15.08.2011

  • Какую платформу/тулчейн вы используете? 15.08.2011
  • Какую ОС вы используете? Этого не произойдет в правильной ОС, например. Linux, но, возможно, вы используете, например. cygwin под виндой? 15.08.2011
  • Если это Windows (а я на 100% уверен, что это так, поскольку я много раз боролся с этим на протяжении многих лет), единственный надежный способ — это CreateProcess. Большинство других библиотек пропускают флаги, необходимые для предотвращения открытия дочерней консоли. 15.08.2011
  • Чтобы не отображать окно команд, вы также можете попробовать следующее: stackoverflow.com/a/16953192/453673 06.06.2013
  • Вот решение, которое работает! stackoverflow.com/a/43600962/82856 25.02.2021

Ответы:


1

Предполагая, что Windows (поскольку это единственная платформа, где такое поведение является эндемичным):

CreatePipe() для создания каналов, необходимых для общаться и CreateProcess для создания дочерний процесс.

HANDLE StdInHandles[2]; 
HANDLE StdOutHandles[2]; 
HANDLE StdErrHandles[2]; 

CreatePipe(&StdInHandles[0], &StdInHandles[1], NULL, 4096); 
CreatePipe(&StdOutHandles[0], &StdOutHandles[1], NULL, 4096); 
CreatePipe(&StdErrHandles[0], &StdErrHandles[1], NULL, 4096); 


STARTUPINFO si;   memset(&si, 0, sizeof(si));  /* zero out */ 

si.dwFlags =  STARTF_USESTDHANDLES; 
si.hStdInput = StdInHandles[0];  /* read handle */ 
si.hStdOutput = StdOutHandles[1];  /* write handle */
si.hStdError = StdErrHandles[1];  /* write handle */

/* fix other stuff in si */

PROCESS_INFORMATION pi; 
/* fix stuff in pi */


CreateProcess(AppName, commandline, SECURITY_ATTRIBUTES, SECURITY_ATTRIBUTES, FALSE, CREATE_NO_WINDOW |DETACHED_PROCESS, lpEnvironment, lpCurrentDirectory, &si, &pi); 

Это должно больше, чем помочь вам сделать то, чего вы хотите достичь.

15.08.2011
  • Извините. Какие нужны библиотеки? 16.08.2011
  • Ссылки на документацию MSDN точно сообщают вам, какие заголовки и библиотеки следует включать, но в данном случае это библиотека ядра WIN32 kernel32. 16.08.2011
  • Полезно, но мне пришлось использовать разные флаги, чтобы заставить его работать. См. это: stackoverflow.com/a/16953192/453673 06.06.2013
  • Мне не удалось получить вывод процесса, когда я использовал флаг DETACHED_PROCESS. 20.06.2019

  • 2

    С POSIX это должно быть примерно так:

    //Create the pipe.
    int lsOutPipe[2];
    pipe(lsOutPipe);
    
    //Fork to two processes.
    pid_t lsPid=fork();
    
    //Check if I'm the child or parent.
    if ( 0 == lsPid )
    {//I'm the child.
      //Close the read end of the pipe.
      close(lsOutPipe[0]);
    
      //Make the pipe be my stdout.
      dup2(lsOutPipe[1],STDOUT_FILENO);
    
      //Replace my self with ls (using one of the exec() functions):
      exec("ls"....);//This never returns.  
    } // if
    
    //I'm the parent.
    //Close the read side of the pipe.
    close(lsOutPipe[1]);
    
    //Read stuff from ls:
    char buffer[1024];
    int bytesRead;
    do
    {
      bytesRead = read(emacsInPipe[0], buffer, 1024);
    
      // Do something with the read information.
      if (bytesRead > 0) printf(buffer, bytesRead);
    } while (bytesRead > 0);
    

    Вы должны, конечно, проверить возвращаемые значения и т.д...

    15.08.2011
  • что такое труба? Visual Studio выделила это слово. 16.08.2011
  • Должна ли быть включена какая-либо библиотека? 16.08.2011
  • POSIX является стандартом для Unix-подобных операционных систем. Windows не входит в их число. Этот код предназначен для Windows. 30.07.2013

  • 3

    Может быть, что-то вроде этого? Этот код вернет вывод, но он должен дождаться завершения процесса.

    #include <iostream>
    #include <windows.h>
    
    int runCmd(const char* cmd, std::string& outOutput) {
    
        HANDLE g_hChildStd_OUT_Rd = NULL;
        HANDLE g_hChildStd_OUT_Wr = NULL;
        HANDLE g_hChildStd_ERR_Rd = NULL;
        HANDLE g_hChildStd_ERR_Wr = NULL;
    
        SECURITY_ATTRIBUTES sa;
        // Set the bInheritHandle flag so pipe handles are inherited.
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;
        if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0))     { return 1; } // Create a pipe for the child process's STDERR.
        if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { return 1; } // Ensure the read handle to the pipe for STDERR is not inherited.
        if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0))     { return 1; } // Create a pipe for the child process's STDOUT.
        if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { return 1; } // Ensure the read handle to the pipe for STDOUT is not inherited
    
        PROCESS_INFORMATION piProcInfo;
        STARTUPINFO siStartInfo;
        bool bSuccess = FALSE;
    
        // Set up members of the PROCESS_INFORMATION structure.
        ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
    
        // Set up members of the STARTUPINFO structure.
        // This structure specifies the STDERR and STDOUT handles for redirection.
        ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
        siStartInfo.cb = sizeof(STARTUPINFO);
        siStartInfo.hStdError  = g_hChildStd_ERR_Wr;
        siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
        siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
    
        // Create the child process.
        bSuccess = CreateProcess(
            NULL,             // program name
            (char*)cmd,       // command line
            NULL,             // process security attributes
            NULL,             // primary thread security attributes
            TRUE,             // handles are inherited
            CREATE_NO_WINDOW, // creation flags (this is what hides the window)
            NULL,             // use parent's environment
            NULL,             // use parent's current directory
            &siStartInfo,     // STARTUPINFO pointer
            &piProcInfo       // receives PROCESS_INFORMATION
        );
    
        CloseHandle(g_hChildStd_ERR_Wr);
        CloseHandle(g_hChildStd_OUT_Wr);
    
        // read output
        #define BUFSIZE 4096
        DWORD dwRead;
        CHAR chBuf[BUFSIZE];
        bool bSuccess2 = FALSE;
        for (;;) { // read stdout
            bSuccess2 = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
            if(!bSuccess2 || dwRead == 0) break;
            std::string s(chBuf, dwRead);
            outOutput += s;
        }
        dwRead = 0;
        for (;;) { // read stderr
            bSuccess2 = ReadFile(g_hChildStd_ERR_Rd, chBuf, BUFSIZE, &dwRead, NULL);
            if(!bSuccess2 || dwRead == 0) break;
            std::string s(chBuf, dwRead);
            outOutput += s;
        }
    
        // The remaining open handles are cleaned up when this process terminates.
        // To avoid resource leaks in a larger application,
        // close handles explicitly.
        return 0;
    }
    
    int main(int argc, char* argv[]) {
    
        std::string output;
        runCmd("cmd /c dir", output);
    
        std::cout << output << std::endl;
    
        return 0;
    }
    
    29.12.2019

    4

    Мне нужно было решить эту проблему для моего полноэкранного приложения OpenGL для Windows, но я не смог предотвратить появление окна консоли. Вместо этого возврат фокуса после небольшой задержки, кажется, работает достаточно хорошо, чтобы его не видеть.

    _popen(cmd, "wb");
    
    Sleep(100);
    
    ShowWindow(hWnd, SW_SHOWDEFAULT);
    SetForegroundWindow(hWnd);
    

    Обновление: это, по-видимому, не работает, если программа запускается из Проводника. Он работает при запуске из Visual Studio.

    27.12.2016
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..