Redirecting Standard Output to a CEdit Control

Environment: The demo was built with Microsoft Developer Studio 97 (Visual C++ 5.0) and has been tested with Windows 95, Windows 98 and Windows NT 4.0.

Applications sometimes need to create a child process whose output may, by default, be written to a console window. Running a batch file is a good example of this. In many cases the console window goes away as soon as the child process exits. At times it would be useful if there was a way to redirect the output of the child process to a CEdit control.

A good example of the desired behavior is the output generated by tools executed from the Tools menu of DevStudio. A tool's output is written to the Output window, and the user can copy and clear text from this window. Moreover, the output from the tool is displayed as it is being written, instead of all at once when the tool exits.

It would be nice if Microsoft had provided an example of how to do this, but such is not the case. The only example that I could find in the Online Documentation is the one titled "Creating a Child Process with Redirected Input and Output". This example shows how to create a child process and redirect its standard output to an anonymous pipe. The parent process writes and then reads to the pipe, while the child process reads and then writes to the pipe, and that's it. This example falls short of demonstrating how to use a loop to read data from a pipe whenever data is available, and to exit the loop when the child process has exited.

I spent a good amount of time searching newsgroups and web sites for examples but never found any that worked to my liking. Then I came across a post to the microsoft.public.vc.mfc newsgroup, submitted by Dima Shamroni, that provides the essential code. I have used this code as a basis for the following class, CRedirect.

The class CRedirect creates a child process and redirects its standard output and standard error to a CEdit control. Both the command line for the process and the CEdit control are specified by the caller.

Using the class is simple, as shown in the following:


CRedirect Redirect("C:\\Temp\\sample.bat", m_Edit);
Redirect.Run();
A fancier way of using this class is to dynamically allocate an object of CRedirect and provide a Stop button that allows you to terminate the child process, as shown in the following (an abbreviated version of what's used in the demo):

CRedirectDemoDlg::OnButtonRun()
{
 m_pRedirect = new CRedirect("C:\\Temp\\sample.bat", m_Edit);
 m_pRedirect->Run();
 delete m_pRedirect;
 m_pRedirect = 0;
}

CRedirectDemoDlg::OnButtonStop()
{
 if ( m_pRedirect )
 {
  m_pRedirect->Stop();
 }
The CRedirect::Run() method blocks the caller. However, windows still receive messages because within the CRedirect::Run() method there is a loop that both reads data from a pipe and calls the method listed below to process window messages.

CRedirect::PeekAndPump()
{
 MSG Msg;
 while ( ::PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE) )
 {
  (void)AfxGetApp()->PumpMessage();
 }
}

Download demo project - 23 KB

Download source - 4 KB

Date Last Updated: March 4, 1999



Comments

  • Thanks alot!

    Posted by Legacy on 01/09/2004 12:00am

    Originally posted by: Dante Shamest

    Although your code used MFC, I was able to adapt it for my pure Win32 application.

    Great work!! :D

    Reply
  • UNICODE Error

    Posted by Legacy on 02/24/2003 12:00am

    Originally posted by: Claude Wynne

    I was getting garbage output.  I'm running on Windows XP but it seems that the output from the redirected standard output is in ANSI not UNICODE. I made the following changes in Redirect.cpp to get it to work:
    
    

    // Change the declaration for PipeData"

    //TCHAR PipeData[BUF_SIZE];
    char PipeData[BUF_SIZE];

    // Change the call to AppendText(PipeData) :

    //AppendText(PipeData);
    AppendText(CString(PipeData));

    // Change the search for "Press any key to continue"

    //TCHAR *ptr = _tcsstr(PipeData, _T("Press any key to continue . . ."));

    CHAR *ptr = strstr(PipeData, "Press any key to continue . . .");

    • Thank you very much,

      Posted by cuongdv83 on 01/25/2007 11:28am

      Thank you very much for your help on fixing the UNICODE bug. I have to spend a lot of time to search for this solution since almost programs only output to ANSI format.

      Reply
    Reply
  • Graphical Program Output redirecting

    Posted by Legacy on 11/18/2001 12:00am

    Originally posted by: Mansukh Patidar

    Is it possible to redirect the GDI output?

    Reply
  • Long filename support?

    Posted by Legacy on 11/21/2000 12:00am

    Originally posted by: Nathan Scherdin

    I love this class. :)

    ok, got that out of the way.

    This class does just about everything I could want it to do however I have noticed a problem. If I try to execute a DOS program(don't know about windows) that either has a longfilename or is in a directory that has a longname the class will not execute the program.

    Any help would be appriciated...please.... :)

    Reply
  • A simpler way to do this is....

    Posted by Legacy on 01/18/2000 12:00am

    Originally posted by: salman a khilji

    this class is not able to display the results in 'real time'. I would say a simpler way to do this is to use create process and pass the arguments as something like...
    c:\notepad.txt c:\txt.txt>logfile.log

    and then read back that log file.

    that will bypass all the extra work thru the piping.

    This will allow someone to use the return codes from the child process. If anyone has figured out how to get it to display in real time, let me know.

    Salman

    Reply
  • New line characters showing up in edit box

    Posted by Legacy on 08/06/1999 12:00am

    Originally posted by: Carrie Kimbel

    Thanks for the code. It is working for me, except that the line feed characters (\n) are showing up as bars instead of actual line feeds. A line feed does occur when the edit box runs out of horizontal space. It must be something simple I'm missing. Anyone have advice??? Thanks.


    Figured it out - I needed a \r\n in the console application code instead of just \n

    Reply
  • How do I redirect stdout as well?

    Posted by Legacy on 07/22/1999 12:00am

    Originally posted by: Joe Ismert

    Redirect seems to only redirect messages that come from the application called and doesn't grab everythig thrown to stderr/stdout. for instance if my program calls a dll that throws messages to stdout I want those too. How can I get tehm?

    Reply
  • Extra characters ...

    Posted by Legacy on 06/16/1999 12:00am

    Originally posted by: Gaby

    I tried your output redirection and that's great. Thanks you.
    My only problem is that the Edit Control displays some extra characters after the message that is normally returned by the spawned process (the console application). Do u have any idea of what this could be due to?
    Thanks again.

    Reply
  • Message Broadcasting Process Causes Deadlock -> the solution

    Posted by Legacy on 03/29/1999 12:00am

    Originally posted by: Ben Burnett

    This occurs when the waiting process is waiting in the thread that processes the messages sent to the window
    (the main window thread). 
    
    

    To prevent this deadlock situation the waiting process can wait in a separate thread, leaving the main window thread free to process window messages, or use the MsgWaitForMultipleObjects() API in conjunction with the dispatching messages.

    In the Run member change the folowing;

    void CRedirect::Run()
    {
    //...

    if ( NumBytesRead )
    {
    //...
    }
    else
    {
    //------------------------------------------------------------------
    // If the child process has completed, break out.
    //------------------------------------------------------------------
    /*
    if ( WaitForSingleObject(ProcessInfo.hProcess, 0) == WAIT_OBJECT_0 ) //lint !e1924 (warning about C-style cast)
    {
    break;
    }
    */

    if ( MsgWaitForMultipleObjects( 1, &ProcessInfo.hProcess,
    FALSE, 0, QS_ALLINPUT) == WAIT_OBJECT_0 )
    {
    break;
    }

    //....
    }

    //...
    }

    Reply
  • How do I terminate a Dos child process?

    Posted by Legacy on 03/17/1999 12:00am

    Originally posted by: John Kiapecos

    Is it possible to terminate a DOS program waiting for
    keyboard input [kbhit()] without hitting a key ?

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Savvy enterprises are discovering that the cloud holds the power to transform IT processes and support business objectives. IT departments can use the cloud to redefine the continuum of development and operations—a process that is becoming known as DevOps. Download the Executive Brief DevOps: Why IT Operations Managers Should Care About the Cloud—prepared by Frost & Sullivan and sponsored by IBM—to learn how IBM SmartCloud Application services provide a robust platform that streamlines …

  • In this on-demand webcast, Oracle ACE and Toad Product Architect Bert Scalzo discusses 10 powerful and hidden features in Toad® that help increase your productivity and DB performance. Watch this webcast today.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds