when I use popen to get the output of a command, say dir, it will prompt out a console.
however, can I get the output of a command without the appearance of the console?
I am using Visual C++ and want to make an Library to return the output of some command, say, dir.
Assuming Windows (since this is the only platform where this behavior is endemic):
CreatePipe() to create the pipes necessary to communicate, and CreateProcess to create the child process.
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);
This should more than get you on your way to doing what you wish to accomplish.
Maybe something like this? This code will return the output but it has to wait for the process to finish.
#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;
}
With POSIX it should be something like this:
//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);
You should off course check return values etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With