How to run a Console app from Graphic app and pick up the output
Author |
Message |
Vartan Akopia #1 / 5
|
 How to run a Console app from Graphic app and pick up the output
Hello, I'm trying to execute a console program from a graphic (MFC) application (under Win 95, with VC5), without showing its console, and pick up its standard output (or error) in a CString variable. I think ShellExecute (or ShellExecuteEx) doesn't allow to get program's stdout. So I tryed to do it with CreateProcess redirecting standard handles. If someone has a similar experiance or knows how to do the thing properly, please help. I would really apreciate any help. Here is my code which doesn't work all the time. I'm not sure about some parameters (I marked this lines of the code with ****). BOOL MyExecCommandWithOutput(CString& strList, LPTSTR lpCommandLine , LPVOID lpEnv) /* strList: receives the stdout or stderr lpCommandLine: pointer to the command line lpEnv: pointer to the new environment */ { DWORD dwExitCode; HANDLE hChildStdoutRd , hChildStdoutWr; HANDLE hChildStderrRd , hChildStderrWr; SECURITY_ATTRIBUTES saAttr; PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; // Set up members of SECURITY_ATTRIBUTES structure. ZeroMemory( &saAttr, sizeof(SECURITY_ATTRIBUTES) ); saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); // **** I'm not sure about this saAttr.bInheritHandle = TRUE; if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, PIPEBUF)) MyErrorExit("Stdout pipe creation failed\n"); if (! CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, PIPEBUF)) MyErrorExit("Stdout pipe creation failed\n"); // Set up members of STARTUPINFO structure. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.lpReserved = NULL; siStartInfo.lpReserved2 = NULL; siStartInfo.cbReserved2 = 0; siStartInfo.lpDesktop = NULL; // Use created pipes as stdout and stderr siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdOutput = hChildStdoutWr; siStartInfo.hStdError = hChildStderrWr; // Don't show program's console // **** I'm not sure about this DWORD dwFlag = DETACHED_PROCESS; // Create the child process. BOOL bl; bl = CreateProcess(NULL, lpCommandLine, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited **** I'm not sure about this dwFlag, // creation flags lpEnv, // environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo); // receives PROCESS_INFORMATION if (!bl) MyErrorExit("Create process failed"); if (!GetExitCodeProcess(piProcInfo.hProcess, &dwExitCode)) MyErrorExit("GetExitCodeProcess failed.\n"); // Close the write end of the pipe before reading from the // read end of the pipe. if (! CloseHandle(hChildStdoutWr) || ! CloseHandle(hChildStderrWr) ) MyErrorExit("Closing handle failed"); // Get the results if (dwExitCode != 1) { // Program exited with code 0. // Read the stdout. MyReadFile2Str(strList , hChildStdoutRd); if (! CloseHandle(hChildStdoutRd) || ! CloseHandle(hChildStderrRd) ) MyErrorExit("Closing handle failed"); return TRUE; } else { // Program exited with nonzero code. // Read the stderr. MyReadFile2Str(strList , hChildStderrRd); if (! CloseHandle(hChildStdoutRd) || ! CloseHandle(hChildStderrRd) ) MyErrorExit("Closing handle failed"); return FALSE; } Quote: }
VOID MyReadFile2Str(CString& str , HANDLE hRead) /* str: receives the results hRead: handle to the file to read from */ { str.Empty(); DWORD dwRead; CHAR chBuf[BUFSIZE+1]; // Read output from hRead handle, and write it in the chBuf array. BOOL br; for (;;) { br = ReadFile(hRead, chBuf, BUFSIZE, &dwRead, NULL); if (!br || dwRead == 0) break; strlist += CString(chBuf, dwRead); } return; Quote: }
___________________________________________________________ Vartan Akopian University of Southern California Department of Mathematics 1042 W. 36th Place, DRB 155 Los Angeles, CA 90089-1113
|
Wed, 04 Jul 2001 03:00:00 GMT |
|
 |
Ajay Kalr #2 / 5
|
 How to run a Console app from Graphic app and pick up the output
Look at MSDN article # Q126628 "How to Spawn a Console App and Refdirect Standard Handles". Quote:
>Hello, >I'm trying to execute a console program from a graphic (MFC) >application (under Win 95, with VC5), without showing its console, and >pick up its standard output (or error) in a CString >variable. I think ShellExecute (or ShellExecuteEx) >doesn't allow to get program's stdout. So I tryed to >do it with CreateProcess redirecting standard handles. >If someone has a similar experiance or knows how to do >the thing properly, please help. I would really apreciate >any help. >Here is my code which doesn't work all the time. I'm not >sure about some parameters (I marked this lines of the >code with ****). >BOOL MyExecCommandWithOutput(CString& strList, LPTSTR lpCommandLine , >LPVOID lpEnv) >/* > strList: receives the stdout or stderr > lpCommandLine: pointer to the command line > lpEnv: pointer to the new environment >*/ >{ > DWORD dwExitCode; > HANDLE hChildStdoutRd , hChildStdoutWr; > HANDLE hChildStderrRd , hChildStderrWr; > SECURITY_ATTRIBUTES saAttr; > PROCESS_INFORMATION piProcInfo; > STARTUPINFO siStartInfo; > // Set up members of SECURITY_ATTRIBUTES structure. > ZeroMemory( &saAttr, sizeof(SECURITY_ATTRIBUTES) ); > saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); > // **** I'm not sure about this > saAttr.bInheritHandle = TRUE; > if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, PIPEBUF)) > MyErrorExit("Stdout pipe creation failed\n"); > if (! CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, PIPEBUF)) > MyErrorExit("Stdout pipe creation failed\n"); > // Set up members of STARTUPINFO structure. > ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); > siStartInfo.cb = sizeof(STARTUPINFO); > siStartInfo.lpReserved = NULL; > siStartInfo.lpReserved2 = NULL; > siStartInfo.cbReserved2 = 0; > siStartInfo.lpDesktop = NULL; > // Use created pipes as stdout and stderr > siStartInfo.dwFlags = STARTF_USESTDHANDLES; > siStartInfo.hStdOutput = hChildStdoutWr; > siStartInfo.hStdError = hChildStderrWr; > // Don't show program's console > // **** I'm not sure about this > DWORD dwFlag = DETACHED_PROCESS; > // Create the child process. > BOOL bl; > bl = CreateProcess(NULL, > lpCommandLine, // command line > NULL, // process security attributes > NULL, // primary thread security attributes > TRUE, // handles are inherited **** I'm not sure about this > dwFlag, // creation flags > lpEnv, // environment > NULL, // use parent's current directory > &siStartInfo, // STARTUPINFO pointer > &piProcInfo); // receives PROCESS_INFORMATION > if (!bl) > MyErrorExit("Create process failed"); > if (!GetExitCodeProcess(piProcInfo.hProcess, &dwExitCode)) > MyErrorExit("GetExitCodeProcess failed.\n"); > // Close the write end of the pipe before reading from the > // read end of the pipe. > if (! CloseHandle(hChildStdoutWr) || > ! CloseHandle(hChildStderrWr) ) > MyErrorExit("Closing handle failed"); > // Get the results > if (dwExitCode != 1) { > // Program exited with code 0. > // Read the stdout. > MyReadFile2Str(strList , hChildStdoutRd); > if (! CloseHandle(hChildStdoutRd) || > ! CloseHandle(hChildStderrRd) ) > MyErrorExit("Closing handle failed"); > return TRUE; > } > else { > // Program exited with nonzero code. > // Read the stderr. > MyReadFile2Str(strList , hChildStderrRd); > if (! CloseHandle(hChildStdoutRd) || > ! CloseHandle(hChildStderrRd) ) > MyErrorExit("Closing handle failed"); > return FALSE; > } >} >VOID MyReadFile2Str(CString& str , HANDLE hRead) >/* > str: receives the results > hRead: handle to the file to read from >*/ >{ > str.Empty(); > DWORD dwRead; > CHAR chBuf[BUFSIZE+1]; > // Read output from hRead handle, and write it in the chBuf array. > BOOL br; > for (;;) { > br =
ReadFile(hRead, chBuf, BUFSIZE, &dwRead, NULL); Quote: > if (!br || dwRead == 0) > break; > strlist += CString(chBuf, dwRead); > } > return; >} >___________________________________________________________ >Vartan Akopian >University of Southern California >Department of Mathematics >1042 W. 36th Place, DRB 155 >Los Angeles, CA 90089-1113
|
Wed, 04 Jul 2001 03:00:00 GMT |
|
 |
Dima Shamron #3 / 5
|
 How to run a Console app from Graphic app and pick up the output
Try the following code. It worked for me at least. Hope it will help you also. ........................................................................ SECURITY_ATTRIBUTES lsa; STARTUPINFO si; PROCESS_INFORMATION pi; LPPROCESS_INFORMATION lppi=π HANDLE hReadPipe, hWritePipe; CWaitCursor WaitCursor; lsa.nLength=sizeof(SECURITY_ATTRIBUTES); lsa.lpSecurityDescriptor=NULL; lsa.bInheritHandle=TRUE; if (!CreatePipe(&hReadPipe,&hWritePipe,&lsa,0)) // create the pipe for output { AfxMessageBox("Couldnt create Pipe\n"); return; Quote: }
memset(&si,0,sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); //important part - making SW_HIDE we prevent console to open up si.dwFlags=STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdOutput=hWritePipe; if (!CreateProcess(NULL, "test.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { AfxMessageBox("Couldnt Create Process\r\n"); return; Quote: }
DWORD cchReadBuffer; // number of bytes read or to be written CString sText; TCHAR ph[5000]; //lets read our output, while being able to catch the moment of program //shutdown for (;;){ cchReadBuffer = 0; if(!PeekNamedPipe(hReadPipe, // ReadFile is blocking call so we should first ph,1,&cchReadBuffer,NULL,NULL)) // check if we have something to read break; if(cchReadBuffer){ // yes we do, so read it and print out to the edit ctrl if (!ReadFile(hReadPipe, ph, 4096, &cchReadBuffer, // number of bytes actually read NULL)) break; ph[cchReadBuffer] = 0; YourEdit.GetWindowText(sText); sText += ph; YourEdit.SetWindowText(sText); YourEdit.UpdateWindow(); } else // no we don't have anything in the buffer //maybe the program exited if(WaitForSingleObject(pi.hProcess,0) == WAIT_OBJECT_0) break; // so we should exit either Sleep(500); // continue otherwise } Quote: }
CloseHandle(hReadPipe); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(hWritePipe); -- Dima Shamroni Abirnet Ltd., MEMCO Software Company
--- AbirNet, Ltd., A MEMCO Software Company AbirNet provides the next generation in network protection and Internet and Intranet intrusion and abuse protection. AbirNet provides Windows 95 and NT-based software that provides no-overhead see-it-all filtering, blocking, alerting, logging, and scanning. Take a test drive of SessionWall-3 today - go to www.AbirNet.com or ask about SessionWall-3 at (817) 251-7000 or (800)245-1688. --- Quote:
>Hello, >I'm trying to execute a console program from a graphic (MFC) >application (under Win 95, with VC5), without showing its console, and >pick up its standard output (or error) in a CString >variable. I think ShellExecute (or ShellExecuteEx) >doesn't allow to get program's stdout. So I tryed to >do it with CreateProcess redirecting standard handles. >If someone has a similar experiance or knows how to do >the thing properly, please help. I would really apreciate >any help. >Here is my code which doesn't work all the time. I'm not >sure about some parameters (I marked this lines of the >code with ****). >BOOL MyExecCommandWithOutput(CString& strList, LPTSTR lpCommandLine , >LPVOID lpEnv) >/* > strList: receives the stdout or stderr > lpCommandLine: pointer to the command line > lpEnv: pointer to the new environment >*/ >{ > DWORD dwExitCode; > HANDLE hChildStdoutRd , hChildStdoutWr; > HANDLE hChildStderrRd , hChildStderrWr; > SECURITY_ATTRIBUTES saAttr; > PROCESS_INFORMATION piProcInfo; > STARTUPINFO siStartInfo; > // Set up members of SECURITY_ATTRIBUTES structure. > ZeroMemory( &saAttr, sizeof(SECURITY_ATTRIBUTES) ); > saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); > // **** I'm not sure about this > saAttr.bInheritHandle = TRUE; > if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, PIPEBUF)) > MyErrorExit("Stdout pipe creation failed\n"); > if (! CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, PIPEBUF)) > MyErrorExit("Stdout pipe creation failed\n"); > // Set up members of STARTUPINFO structure. > ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); > siStartInfo.cb = sizeof(STARTUPINFO); > siStartInfo.lpReserved = NULL; > siStartInfo.lpReserved2 = NULL; > siStartInfo.cbReserved2 = 0; > siStartInfo.lpDesktop = NULL; > // Use created pipes as stdout and stderr > siStartInfo.dwFlags = STARTF_USESTDHANDLES; > siStartInfo.hStdOutput = hChildStdoutWr; > siStartInfo.hStdError = hChildStderrWr; > // Don't show program's console > // **** I'm not sure about this > DWORD dwFlag = DETACHED_PROCESS; > // Create the child process. > BOOL bl; > bl = CreateProcess(NULL, > lpCommandLine, // command line > NULL, // process security attributes > NULL, // primary thread security attributes > TRUE, // handles are inherited **** I'm not sure about this > dwFlag, // creation flags > lpEnv, // environment > NULL, // use parent's current directory > &siStartInfo, // STARTUPINFO pointer > &piProcInfo); // receives PROCESS_INFORMATION > if (!bl) > MyErrorExit("Create process failed"); > if (!GetExitCodeProcess(piProcInfo.hProcess, &dwExitCode)) > MyErrorExit("GetExitCodeProcess failed.\n"); > // Close the write end of the pipe before reading from the > // read end of the pipe. > if (! CloseHandle(hChildStdoutWr) || > ! CloseHandle(hChildStderrWr) ) > MyErrorExit("Closing handle failed"); > // Get the results > if (dwExitCode != 1) { > // Program exited with code 0. > // Read the stdout. > MyReadFile2Str(strList , hChildStdoutRd); > if (! CloseHandle(hChildStdoutRd) || > ! CloseHandle(hChildStderrRd) ) > MyErrorExit("Closing handle failed"); > return TRUE; > } > else { > // Program exited with nonzero code. > // Read the stderr. > MyReadFile2Str(strList , hChildStderrRd); > if (! CloseHandle(hChildStdoutRd) || > ! CloseHandle(hChildStderrRd) ) > MyErrorExit("Closing handle failed"); > return FALSE; > } >} >VOID MyReadFile2Str(CString& str , HANDLE hRead) >/* > str: receives the results > hRead: handle to the file to read from >*/ >{ > str.Empty(); > DWORD dwRead; > CHAR chBuf[BUFSIZE+1]; > // Read output from hRead handle, and write it in the chBuf array. > BOOL br; > for (;;) { > br = ReadFile(hRead, chBuf, BUFSIZE, &dwRead, NULL); > if (!br || dwRead == 0) > break; > strlist += CString(chBuf, dwRead); > } > return; >} >___________________________________________________________ >Vartan Akopian >University of Southern California >Department of Mathematics >1042 W. 36th Place, DRB 155 >Los Angeles, CA 90089-1113
|
Thu, 05 Jul 2001 03:00:00 GMT |
|
 |
Matt Brun #4 / 5
|
 How to run a Console app from Graphic app and pick up the output
Quote:
> Try the following code. It worked for me at least. Hope it will > help you also.
[Snip] I've been trying to do this for some time now, but your example is the only one that has ever worked the way I want. Thanks, --Matt
|
Sat, 07 Jul 2001 03:00:00 GMT |
|
 |
Vartan Akopia #5 / 5
|
 How to run a Console app from Graphic app and pick up the output
Thanks very much for your code. It worked very well. And especially it solved one of the major problems I had: ReadFile() was blocking. Again Thanks. Vartan
Try the following code. It worked for me at least. Hope it will help you also. ........................................................................ SECURITY_ATTRIBUTES lsa; STARTUPINFO si; PROCESS_INFORMATION pi; LPPROCESS_INFORMATION lppi=π HANDLE hReadPipe, hWritePipe; CWaitCursor WaitCursor; lsa.nLength=sizeof(SECURITY_ATTRIBUTES); lsa.lpSecurityDescriptor=NULL; lsa.bInheritHandle=TRUE; if (!CreatePipe(&hReadPipe,&hWritePipe,&lsa,0)) // create the pipe for output { AfxMessageBox("Couldnt create Pipe\n"); return; Quote: }
memset(&si,0,sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); //important part - making SW_HIDE we prevent console to open up si.dwFlags=STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdOutput=hWritePipe; if (!CreateProcess(NULL, "test.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { AfxMessageBox("Couldnt Create Process\r\n"); return; Quote: }
DWORD cchReadBuffer; // number of bytes read or to be written CString sText; TCHAR ph[5000]; //lets read our output, while being able to catch the moment of program //shutdown for (;;){ cchReadBuffer = 0; if(!PeekNamedPipe(hReadPipe, // ReadFile is blocking call so we should first ph,1,&cchReadBuffer,NULL,NULL)) // check if we have something to read break; if(cchReadBuffer){ // yes we do, so read it and print out to the edit ctrl if (!ReadFile(hReadPipe, ph, 4096, &cchReadBuffer, // number of bytes actually read NULL)) break; ph[cchReadBuffer] = 0; YourEdit.GetWindowText(sText); sText += ph; YourEdit.SetWindowText(sText); YourEdit.UpdateWindow(); } else // no we don't have anything in the buffer //maybe the program exited if(WaitForSingleObject(pi.hProcess,0) == WAIT_OBJECT_0) break; // so we should exit either Sleep(500); // continue otherwise } Quote: }
CloseHandle(hReadPipe); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(hWritePipe); ___________________________________________________________ Vartan Akopian University of Southern California Department of Mathematics 1042 W. 36th Place, DRB 155 Los Angeles, CA 90089-1113
|
Sat, 07 Jul 2001 03:00:00 GMT |
|
|
|