How do I execute a command and get the output of the command within C++ using POSIX?

前端 未结 11 1157
我在风中等你
我在风中等你 2020-11-21 05:39

I am looking for a way to get the output of a command when it is run from within a C++ program. I have looked at using the system() function, but that will jus

11条回答
  •  不思量自难忘°
    2020-11-21 06:01

    For Windows, popen also works, but it opens up a console window - which quickly flashes over your UI application. If you want to be a professional, it's better to disable this "flashing" (especially if the end-user can cancel it).

    So here is my own version for Windows:

    (This code is partially recombined from ideas written in The Code Project and MSDN samples.)

    #include 
    #include 
    //
    // Execute a command and get the results. (Only standard output)
    //
    CStringA ExecCmd(
        const wchar_t* cmd              // [in] command to execute
    )
    {
        CStringA strResult;
        HANDLE hPipeRead, hPipeWrite;
    
        SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES)};
        saAttr.bInheritHandle = TRUE; // Pipe handles are inherited by child process.
        saAttr.lpSecurityDescriptor = NULL;
    
        // Create a pipe to get results from child's stdout.
        if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
            return strResult;
    
        STARTUPINFOW si = {sizeof(STARTUPINFOW)};
        si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        si.hStdOutput  = hPipeWrite;
        si.hStdError   = hPipeWrite;
        si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing.
                                  // Requires STARTF_USESHOWWINDOW in dwFlags.
    
        PROCESS_INFORMATION pi = { 0 };
    
        BOOL fSuccess = CreateProcessW(NULL, (LPWSTR)cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
        if (! fSuccess)
        {
            CloseHandle(hPipeWrite);
            CloseHandle(hPipeRead);
            return strResult;
        }
    
        bool bProcessEnded = false;
        for (; !bProcessEnded ;)
        {
            // Give some timeslice (50 ms), so we won't waste 100% CPU.
            bProcessEnded = WaitForSingleObject( pi.hProcess, 50) == WAIT_OBJECT_0;
    
            // Even if process exited - we continue reading, if
            // there is some data available over pipe.
            for (;;)
            {
                char buf[1024];
                DWORD dwRead = 0;
                DWORD dwAvail = 0;
    
                if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
                    break;
    
                if (!dwAvail) // No data available, return
                    break;
    
                if (!::ReadFile(hPipeRead, buf, min(sizeof(buf) - 1, dwAvail), &dwRead, NULL) || !dwRead)
                    // Error, the child process might ended
                    break;
    
                buf[dwRead] = 0;
                strResult += buf;
            }
        } //for
    
        CloseHandle(hPipeWrite);
        CloseHandle(hPipeRead);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return strResult;
    } //ExecCmd
    

提交回复
热议问题