Solved

Capturing output from console program

Posted on 1998-06-01
9
415 Views
Last Modified: 2013-12-03
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,lpszCmdParam);
  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.left,
                        hWndRect.bottom-hWndRect.top,                      
                SWP_NOZORDER | SWP_SHOWWINDOW);
                  if((hThread = CreateThread(
                                                                        NULL,
                                                                        0,
                                                                        (LPTHREAD_START_ROUTINE)command_external,
                                                                        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.lpSecurityDescriptor = 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_HANDLE, hChildStdoutWr))
      MessageBox(ghWnd,"Redirecting 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_HANDLE, hChildStdinRd))
      MessageBox(ghWnd,"Redirecting Stdin failed","Error",MB_OK);
 
  // Duplicate the write handle to the pipe so it is not inherited.
  fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
      GetCurrentProcess(), &hChildStdinWrDup, 0,
      FALSE,       // not inherited
      DUPLICATE_SAME_ACCESS);
  if (! fSuccess)
        MessageBox(ghWnd,"DuplicateHandle 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_PRIORITY_CLASS,
      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_HANDLE);
      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(chBuf));
            peek_result = PeekNamedPipe(hChildStdoutRd,chBuf,4096,&dwRead, &dwAvail, &dwUnRead);
            if((dwRead == 0) && (dwAvail == 0) && (dwUnRead == 0))
            {
                  //if process has finished  createprocess
                  GetExitCodeProcess(piProcInfo.hProcess,&dwExitCode);
                  if(dwExitCode != STILL_ACTIVE)
                  {
                        if(any_output == TRUE)
                        {
                              peek_result = PeekNamedPipe(hChildStdoutRd,chBuf,4096,&dwRead, &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,&chBuf[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_MESSAGE_FROM_SYSTEM,
                                                NULL,
                                                lerror_num,
                                                MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),
                                                tmpstr,
                                                sizeof(tmpstr),
                                                NULL);
      sprintf(tmpstr2,"Error %li = %s",lerror_num,tmpstr);
      MessageBox(ghWnd,tmpstr2,"Error",MB_OK);
}


0
Comment
Question by:bbarber
  • 5
  • 4
9 Comments
 
LVL 23

Expert Comment

by:chensu
ID: 1405630
Take the following samples and run them on the three machines. If you encounter the same problem, your program should be OK. Otherwise, you need to look into these samples to see what is wrong with your program.

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\INHERIT
0
 

Author Comment

by:bbarber
ID: 1405631
The artical's referenced in your response where unreachable and the pointers failed

Can you check them and resubmit?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1405632
Microsoft seems to have removed the first KB article. You can get it from MSDN Library CDs. This article does not contain much information.
0
 

Author Comment

by:bbarber
ID: 1405633
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.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 23

Expert Comment

by:chensu
ID: 1405634
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.
0
 

Author Comment

by:bbarber
ID: 1405635
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.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1405636
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.
0
 

Author Comment

by:bbarber
ID: 1405637
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.
0
 
LVL 23

Accepted Solution

by:
chensu earned 250 total points
ID: 1405638
Q: Why does this work differently on some machines?

A: There is something wrong with the machines not your code.

Q: How can I fix it???

A: You fixed it by yourself.


I still feel that this is one of my worst answers. Actually, what I provided is not an answer but a clue.

Thank you and happy programming.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
how to bring to back always mid parent image form 21 77
SQL to ElasticSearch Query 1 577
What .NET website keeps me current? 9 54
Recommendation vb6 to vb.net or others 14 105
This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now