Revision: 27688
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at June 21, 2010 12:22 by jimfred
Initial Code
// Execute a command and get the results in a CString. // Synchronously launches a child process and waits up to 2 seconds for completion. // Uses a pipe to get the output of the child process. // Does not pipe to stdin of child process. // Example usage: // CString str; // str = ExecCmd( "ping 127.0.0.1 -n 99 " ); // This ping command will be terminated early before the -n 99 completes. // str.Replace( "\x0d\x0d\x0a", "\x0d\x0a" ); // fixes some ugly non-standard line terminators created by ping. // // str = ExecCmd( "java -version" ); // A more practical usage. // CString ExecCmd( LPCSTR pCmdArg) { // Handle Inheritance - to pipe child's stdout via pipes to parent, handles must be inherited. // SECURITY_ATTRIBUTES.bInheritHandle must be TRUE // CreateProcess parameter bInheritHandles must be TRUE; // STARTUPINFO.dwFlags must have STARTF_USESTDHANDLES set. CString strResult; // Contains result of cmdArg. HANDLE hChildStdoutRd; // Read-side, used in calls to ReadFile() to get child's stdout output. HANDLE hChildStdoutWr; // Write-side, given to child process using si struct. BOOL fSuccess; // Create security attributes to create pipe. SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES)} ; saAttr.bInheritHandle = TRUE; // Set the bInheritHandle flag so pipe handles are inherited by child process. Required. saAttr.lpSecurityDescriptor = NULL; // Create a pipe to get results from child's stdout. // I'll create only 1 because I don't need to pipe to the child's stdin. if ( !CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) ) { return strResult; } STARTUPINFO si = { sizeof(STARTUPINFO) }; // specifies startup parameters for child process. si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required. si.hStdOutput = hChildStdoutWr; // Requires STARTF_USESTDHANDLES in dwFlags. si.hStdError = hChildStdoutWr; // Requires STARTF_USESTDHANDLES in dwFlags. // si.hStdInput remains null. si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags. PROCESS_INFORMATION pi = { 0 }; // Create the child process. fSuccess = CreateProcess( NULL, (LPSTR)pCmdArg, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // TRUE=handles are inherited. Required. CREATE_NEW_CONSOLE, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &si, // __in, STARTUPINFO pointer &pi); // __out, receives PROCESS_INFORMATION if (! fSuccess) { return strResult; } // Wait until child processes exit. Don't wait forever. WaitForSingleObject( pi.hProcess, 2000 ); TerminateProcess( pi.hProcess, 0 ); // Kill process if it is still running. Tested using cmd "ping blah -n 99" // Close the write end of the pipe before reading from the read end of the pipe. if (!CloseHandle(hChildStdoutWr)) { return strResult; } // Read output from the child process. for (;;) { DWORD dwRead; CHAR chBuf[4096]; // Read from pipe that is the standard output for child process. bool done = !ReadFile( hChildStdoutRd, chBuf, 4096, &dwRead, NULL) || dwRead == 0; if( done ) { break; } // Append result to string. strResult += CString( chBuf, dwRead) ; } // Close process and thread handles. CloseHandle( hChildStdoutRd ); // CreateProcess docs specify that these must be closed. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return strResult; }
Initial URL
Initial Description
Do the equivalent of ShellExecute or the Win16-compatible WinExec: Run a command. But, get the command's stdout output in a CString.
Initial Title
MFC, run command such as "ping 127.0.0.1" and get stdout in a CString.
Initial Tags
Initial Language
C++