bbarber
asked on
Capturing output from console program
Why does this work differently on some machines and how
can I fix it??? To run it set up a shortcut for then program (external.exe) then add command line
parameters (ie: change Target: C:\test\external.exe c:\dos\pkunzip -v c:\new\*.zip). Oh and just
to be sure you know, the program is supposed to kick off a dos or console application and
display the output in the window only.
Machine #1
Zenith Pentium 100
Win95 ver 4.00.095
Works perfectly!!!
Machine #2
Compaq Pentium 200
Win95 ver 4.00.111
Checks floppy drive and external program never runs, produces no output
Machine #3
Micron Pentium 200
Win95 ver 4.00.111
Checks floppy drive and then external program starts and produces output fine.
Here's the source code :
#include <windows.h>
#include <windowsx.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <process.h>
//************* FUNCTION DECLARATIONS ************************** ***
int pascal WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdParam, int nCmdShow);
long CALLBACK MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void command_external(void);
VOID ReadFromPipe(void);
void show_error_text(void);
//**************** SOME GLOBALS VARIABLES **************************
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr,
hInputFile, hSaveStdin, hSaveStdout;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
DWORD dwRead, dwAvail, dwUnRead, dwExitCode, dwWrite;
DWORD dwStartup;
char chBuf[4096];
char ExternalCommandLine[2048];
BOOL peek_result;
HWND ghWnd;
HINSTANCE ghInst;
HFONT hfont;
//****************** START OF PROGRAM **************************
int pascal WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Msg;
WNDCLASS wc;
strcpy(ExternalCommandLine ,lpszCmdPa ram);
memset(&wc, 0, sizeof(WNDCLASS));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.hInstance = hInst;
wc.hIcon = NULL; //LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN_ICON ) );
wc.hbrBackground = GetStockObject(WHITE_BRUSH );
wc.lpszClassName = "DS-External";
RegisterClass(&wc);
hWnd = CreateWindow("DS-External" , //classname
"DS-External", //winname
WS_OVERLAPPEDWINDOW,
0, 0,
640, 480,
NULL,
NULL,
hInst,
NULL );
ghWnd = hWnd;
ghInst = hInst;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hfont = CreateFont( 12,5,
0,0,
FW_DONTCARE,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_MODERN | FIXED_PITCH,
NULL);
while ( GetMessage( &Msg, NULL, 0, 0 ) )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (Msg.wParam);
}
long CALLBACK MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
RECT hDesktopRect, hWndRect;
switch(message)
{
case WM_CREATE:
{
DWORD thread_id;
HANDLE hThread;
GetClientRect( GetDesktopWindow(), &hDesktopRect);
GetWindowRect(hWnd, &hWndRect);
SetWindowPos(hWnd, (HWND) NULL,
(hDesktopRect.right / 2) - ((hWndRect.right-hWndRect. left) / 2),
(hDesktopRect.bottom / 2) - ((hWndRect.bottom-hWndRect .top) / 2) - 16,
hWndRect.right-hWndRect.le ft,
hWndRect.bottom-hWndRect.t op,
SWP_NOZORDER | SWP_SHOWWINDOW);
if((hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)co mmand_exte rnal,
NULL,
0,
&thread_id)) == NULL)
{
MessageBox(ghWnd,"**** Failed to create External Thread ****","Error",MB_OK);
}
return(0); //Continue Creation
break;
}
case WM_DESTROY:
{
DeleteObject(hfont);
PostQuitMessage(0);
return(0);
break;
}
default:
{
return (DefWindowProc(hWnd, message, wParam, lParam));
}
}
}
void command_external(void)
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES );
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescripto r = NULL;
// Create a pipe for the child's STDOUT.
if (! CreatePipe(&hChildStdoutRd , &hChildStdoutWr, &saAttr, 4096))
MessageBox(ghWnd,"Stdout pipe creation failed\n","Error",MB_OK);
// Set a write handle to the pipe to be STDOUT.
if (! SetStdHandle(STD_OUTPUT_HA NDLE, hChildStdoutWr))
MessageBox(ghWnd,"Redirect ing STDOUT failed","Error",MB_OK);
// Create a pipe for the child's STDIN.
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 4096))
MessageBox(ghWnd,"Stdin pipe creation failed\n","Error",MB_OK);
// Set a read handle to the pipe to be STDIN.
if (! SetStdHandle(STD_INPUT_HAN DLE, hChildStdinRd))
MessageBox(ghWnd,"Redirect ing Stdin failed","Error",MB_OK);
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrent Process(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);
if (! fSuccess)
MessageBox(ghWnd,"Duplicat eHandle failed","Error",MB_OK);
CloseHandle(hChildStdinWr) ;
// Now create the child process.
// Set up members of STARTUPINFO structure.
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.lpReserved = NULL;
siStartInfo.lpReserved2 = NULL;
siStartInfo.cbReserved2 = 0;
siStartInfo.lpDesktop = NULL;
//siStartInfo.dwFlags = 0;
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdoutRd;
siStartInfo.hStdOutput = hChildStdoutWr;
// Create the child process.
if(CreateProcess(NULL,
ExternalCommandLine,
NULL,
NULL,
TRUE,
DETACHED_PROCESS|NORMAL_PR IORITY_CLA SS,
NULL,
NULL,
&siStartInfo,
&piProcInfo) == FALSE)
MessageBox(ghWnd,"Create process failed","Error",MB_OK);
ReadFromPipe();
MessageBox(ghWnd,"external command Completed!","Done",MB_OK);
}
VOID ReadFromPipe(void)
{
DWORD dwRead, dwAvail, dwUnRead, dwExitCode;
char chBuf[4096];
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HA NDLE);
BOOL peek_result;
BOOL any_output;
int posx,posy,chidx;
HDC hdc;
posx = 0; posy = 0;
/*
* Close the write end of the pipe before reading from the
* read end of the pipe.
*/
if (! CloseHandle(hChildStdoutWr ))
MessageBox(ghWnd,"Closing handle failed","Error",MB_OK);
/* Read output from child, and write it to parent's STDOUT. */
any_output = FALSE;
for (;;)
{
memset(chBuf,'\0',sizeof(c hBuf));
peek_result = PeekNamedPipe(hChildStdout Rd,chBuf,4 096,&dwRea d, &dwAvail, &dwUnRead);
if((dwRead == 0) && (dwAvail == 0) && (dwUnRead == 0))
{
//if process has finished createprocess
GetExitCodeProcess(piProcI nfo.hProce ss,&dwExit Code);
if(dwExitCode != STILL_ACTIVE)
{
if(any_output == TRUE)
{
peek_result = PeekNamedPipe(hChildStdout Rd,chBuf,4 096,&dwRea d, &dwAvail, &dwUnRead);
if((dwRead == 0) && (dwAvail == 0) && (dwUnRead == 0))
{
break;
}
else
{
peek_result = TRUE;
}
}
}
Sleep(100);
continue;
}
ReadFile(hChildStdoutRd, chBuf, 4096, &dwRead, NULL);
//*********** output text to window ***********
hdc = GetDC(ghWnd);
for(chidx = 0; chidx < (int)dwRead; chidx++)
{
switch(chBuf[chidx])
{
case 10:
{
break;
}
case 13:
{
posy += 12;
posx = 0;
break;
}
default:
{
SelectObject(hdc,hfont);
TextOut(hdc,posx,posy,&chB uf[chidx], 1);
posx += 5;
break;
}
}
}
ReleaseDC(ghWnd, hdc);
//************************ ********** ********** *
any_output = TRUE;
}
}
void show_error_text(void)
{
char tmpstr[256];
char tmpstr2[280];
DWORD lerror_num;
lerror_num = GetLastError();
FormatMessage(FORMAT_MESSA GE_FROM_SY STEM,
NULL,
lerror_num,
MAKELANGID(LANG_NEUTRAL,SU BLANG_SYS_ DEFAULT),
tmpstr,
sizeof(tmpstr),
NULL);
sprintf(tmpstr2,"Error %li = %s",lerror_num,tmpstr);
MessageBox(ghWnd,tmpstr2," Error",MB_ OK);
}
can I fix it??? To run it set up a shortcut for then program (external.exe) then add command line
parameters (ie: change Target: C:\test\external.exe c:\dos\pkunzip -v c:\new\*.zip). Oh and just
to be sure you know, the program is supposed to kick off a dos or console application and
display the output in the window only.
Machine #1
Zenith Pentium 100
Win95 ver 4.00.095
Works perfectly!!!
Machine #2
Compaq Pentium 200
Win95 ver 4.00.111
Checks floppy drive and external program never runs, produces no output
Machine #3
Micron Pentium 200
Win95 ver 4.00.111
Checks floppy drive and then external program starts and produces output fine.
Here's the source code :
#include <windows.h>
#include <windowsx.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <process.h>
//************* FUNCTION DECLARATIONS **************************
int pascal WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdParam, int nCmdShow);
long CALLBACK MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void command_external(void);
VOID ReadFromPipe(void);
void show_error_text(void);
//**************** SOME GLOBALS VARIABLES **************************
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr,
hInputFile, hSaveStdin, hSaveStdout;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
DWORD dwRead, dwAvail, dwUnRead, dwExitCode, dwWrite;
DWORD dwStartup;
char chBuf[4096];
char ExternalCommandLine[2048];
BOOL peek_result;
HWND ghWnd;
HINSTANCE ghInst;
HFONT hfont;
//****************** START OF PROGRAM **************************
int pascal WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Msg;
WNDCLASS wc;
strcpy(ExternalCommandLine
memset(&wc, 0, sizeof(WNDCLASS));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.hInstance = hInst;
wc.hIcon = NULL; //LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN_ICON ) );
wc.hbrBackground = GetStockObject(WHITE_BRUSH
wc.lpszClassName = "DS-External";
RegisterClass(&wc);
hWnd = CreateWindow("DS-External"
"DS-External", //winname
WS_OVERLAPPEDWINDOW,
0, 0,
640, 480,
NULL,
NULL,
hInst,
NULL );
ghWnd = hWnd;
ghInst = hInst;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hfont = CreateFont( 12,5,
0,0,
FW_DONTCARE,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_MODERN | FIXED_PITCH,
NULL);
while ( GetMessage( &Msg, NULL, 0, 0 ) )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (Msg.wParam);
}
long CALLBACK MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
RECT hDesktopRect, hWndRect;
switch(message)
{
case WM_CREATE:
{
DWORD thread_id;
HANDLE hThread;
GetClientRect( GetDesktopWindow(), &hDesktopRect);
GetWindowRect(hWnd, &hWndRect);
SetWindowPos(hWnd, (HWND) NULL,
(hDesktopRect.right / 2) - ((hWndRect.right-hWndRect.
(hDesktopRect.bottom / 2) - ((hWndRect.bottom-hWndRect
hWndRect.right-hWndRect.le
hWndRect.bottom-hWndRect.t
SWP_NOZORDER | SWP_SHOWWINDOW);
if((hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)co
NULL,
0,
&thread_id)) == NULL)
{
MessageBox(ghWnd,"**** Failed to create External Thread ****","Error",MB_OK);
}
return(0); //Continue Creation
break;
}
case WM_DESTROY:
{
DeleteObject(hfont);
PostQuitMessage(0);
return(0);
break;
}
default:
{
return (DefWindowProc(hWnd, message, wParam, lParam));
}
}
}
void command_external(void)
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescripto
// Create a pipe for the child's STDOUT.
if (! CreatePipe(&hChildStdoutRd
MessageBox(ghWnd,"Stdout pipe creation failed\n","Error",MB_OK);
// Set a write handle to the pipe to be STDOUT.
if (! SetStdHandle(STD_OUTPUT_HA
MessageBox(ghWnd,"Redirect
// Create a pipe for the child's STDIN.
if (! CreatePipe(&hChildStdinRd,
MessageBox(ghWnd,"Stdin pipe creation failed\n","Error",MB_OK);
// Set a read handle to the pipe to be STDIN.
if (! SetStdHandle(STD_INPUT_HAN
MessageBox(ghWnd,"Redirect
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrent
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);
if (! fSuccess)
MessageBox(ghWnd,"Duplicat
CloseHandle(hChildStdinWr)
// Now create the child process.
// Set up members of STARTUPINFO structure.
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.lpReserved = NULL;
siStartInfo.lpReserved2 = NULL;
siStartInfo.cbReserved2 = 0;
siStartInfo.lpDesktop = NULL;
//siStartInfo.dwFlags = 0;
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdoutRd;
siStartInfo.hStdOutput = hChildStdoutWr;
// Create the child process.
if(CreateProcess(NULL,
ExternalCommandLine,
NULL,
NULL,
TRUE,
DETACHED_PROCESS|NORMAL_PR
NULL,
NULL,
&siStartInfo,
&piProcInfo) == FALSE)
MessageBox(ghWnd,"Create process failed","Error",MB_OK);
ReadFromPipe();
MessageBox(ghWnd,"external
}
VOID ReadFromPipe(void)
{
DWORD dwRead, dwAvail, dwUnRead, dwExitCode;
char chBuf[4096];
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HA
BOOL peek_result;
BOOL any_output;
int posx,posy,chidx;
HDC hdc;
posx = 0; posy = 0;
/*
* Close the write end of the pipe before reading from the
* read end of the pipe.
*/
if (! CloseHandle(hChildStdoutWr
MessageBox(ghWnd,"Closing handle failed","Error",MB_OK);
/* Read output from child, and write it to parent's STDOUT. */
any_output = FALSE;
for (;;)
{
memset(chBuf,'\0',sizeof(c
peek_result = PeekNamedPipe(hChildStdout
if((dwRead == 0) && (dwAvail == 0) && (dwUnRead == 0))
{
//if process has finished createprocess
GetExitCodeProcess(piProcI
if(dwExitCode != STILL_ACTIVE)
{
if(any_output == TRUE)
{
peek_result = PeekNamedPipe(hChildStdout
if((dwRead == 0) && (dwAvail == 0) && (dwUnRead == 0))
{
break;
}
else
{
peek_result = TRUE;
}
}
}
Sleep(100);
continue;
}
ReadFile(hChildStdoutRd, chBuf, 4096, &dwRead, NULL);
//*********** output text to window ***********
hdc = GetDC(ghWnd);
for(chidx = 0; chidx < (int)dwRead; chidx++)
{
switch(chBuf[chidx])
{
case 10:
{
break;
}
case 13:
{
posy += 12;
posx = 0;
break;
}
default:
{
SelectObject(hdc,hfont);
TextOut(hdc,posx,posy,&chB
posx += 5;
break;
}
}
}
ReleaseDC(ghWnd, hdc);
//************************
any_output = TRUE;
}
}
void show_error_text(void)
{
char tmpstr[256];
char tmpstr2[280];
DWORD lerror_num;
lerror_num = GetLastError();
FormatMessage(FORMAT_MESSA
NULL,
lerror_num,
MAKELANGID(LANG_NEUTRAL,SU
tmpstr,
sizeof(tmpstr),
NULL);
sprintf(tmpstr2,"Error %li = %s",lerror_num,tmpstr);
MessageBox(ghWnd,tmpstr2,"
}
ASKER
The artical's referenced in your response where unreachable and the pointers failed
Can you check them and resubmit?
Can you check them and resubmit?
Microsoft seems to have removed the first KB article. You can get it from MSDN Library CDs. This article does not contain much information.
ASKER
Well thats about the worst answer I've ever seen. If I had all the resouces that you have, dont you think I would have already looked at them and gotten past that. I wrote this based on the referenced examples. I ask for a reason whay this didn't work and how to make it work. Not do you know any references. Now I know how you got such a hige Expert score.
You seem to not get the key of my (worst) answer. I suspected that there is something wrong with the machines not your code. So, I asked you to run the samples on these machines to see what happens. Have you tried?
Well, I admit that this is one of my worst answers. It is just a guess.
Regarding my score, if you take a look at the questions I answered, you'll see that I have never cared about the points while some other Experts asked the customers to pay more points. I agree that the points are the credits the customers should give to the Experts because the Experts do their jobs here without any other remuneration. I am here because I just want to help others and to learn from others.
Well, I admit that this is one of my worst answers. It is just a guess.
Regarding my score, if you take a look at the questions I answered, you'll see that I have never cared about the points while some other Experts asked the customers to pay more points. I agree that the points are the credits the customers should give to the Experts because the Experts do their jobs here without any other remuneration. I am here because I just want to help others and to learn from others.
ASKER
I listed just 3 unique examples of the conditions tht I encountered with this program. I have actually run the program on more than 45 seperate computers and the trend is about the same. I listed the more common machines. I work in an area that has over 200 machines and have access to test it on any of them that I want to.
So, have you tried the samples on any of the over 200 machines? If the samples work fine, you may look into them to figure out what the difference is.
I get the points only if the customers accept my answers. It is decided by the customers themselves rather than anybody else.
I get the points only if the customers accept my answers. It is decided by the customers themselves rather than anybody else.
ASKER
Yes, I had tried the samples and my program on the other machines. 45 of them.
It turns out that it's a problem in the bios as recoganized by Win95. We went to my computer, Control Pannel, System, device manager, devices and removed the associations for the system devices. Rebooted the machine(s) that failed/gave unpredictable results and let Win95 rebuild the motherboard information and then the programs worked.
If you want I will accept your answer.
It turns out that it's a problem in the bios as recoganized by Win95. We went to my computer, Control Pannel, System, device manager, devices and removed the associations for the system devices. Rebooted the machine(s) that failed/gave unpredictable results and let Win95 rebuild the motherboard information and then the programs worked.
If you want I will accept your answer.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
How to Spawn a Console App and Redirect Standard Handles
http://support.microsoft.com/support/kb/articles/q126/6/28.asp
Redirection Issues on Windows 95 MS-DOS Apps and Batch Files
http://support.microsoft.com/support/kb/articles/q150/9/56.asp
Platform SDK Code Samples\WINBASE\IPC\INHERI