Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How can I redirect stdout to an EditBox?

183 views
Skip to first unread message

Johnny

unread,
Oct 20, 2002, 12:23:28 PM10/20/02
to
Hi,
I've a C routine that makes a work...
I'm trying to create an User Interface with win32 api's.
How can I redirect the stdout to an EditBox.
I want to use the EditBox like a log window that shows the work of my C
routine. I don't want to replace every "printf" of my routine with a
SetWindowText...
Is there some way to do this?

--
Bye
Johnny


Ted Ferenc

unread,
Oct 20, 2002, 1:08:36 PM10/20/02
to
hav a look at MSDN article.

HOWTO: Spawn Console Processes with Redirected Standard Handles
ID: Q190351

Ted Ferenc
This address used is maintained only for newsgroup posting.
Mail sent there may not be read by me for several days.
"Johnny" <jonqueridoNON...@tin.it.invalid> wrote in message
news:4MAs9.13913$TD1.6...@news2.tin.it...


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.404 / Virus Database: 228 - Release Date: 15/10/02


Uwe Kotyczka

unread,
Oct 21, 2002, 5:52:38 AM10/21/02
to
"Johnny" <jonqueridoNON...@tin.it.invalid> wrote in message news:<4MAs9.13913$TD1.6...@news2.tin.it>...

You can use my class CRedirectStdout (which acts like CWaitCursor:
as long as an instance of CRedirectStdout is present - redirection
happens)

/////////////////////////////////////////////////////////////////////////////
// Copyright:
// Uwe Kotyczka <uwe.ko...@web.de>
// created: April 2000
//
/////////////////////////////////////////////////////////////////////////////
// RedirectStdout.h: Header-Datei
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_REDIRECTSTDOUT_H__E586D748_1CF4_11D4_8B97_00001CD5E4D1__INCLUDED_)
#define AFX_REDIRECTSTDOUT_H__E586D748_1CF4_11D4_8B97_00001CD5E4D1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifdef _DEBUG
class AFX_EXT_CLASS_SPECIAL CRedirectStdout
{
public:
CRedirectStdout();
virtual ~CRedirectStdout();

private:
CWinThread* m_pReadThread;

HANDLE m_hStdoutWrite;
HANDLE m_hStdoutRead;
HANDLE m_hStdoutSave;

static UINT ReadPipeThreadProc(LPVOID pParam);
BOOL StartRedirect();
BOOL EndRedirect();
};
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio fügt zusätzliche Deklarationen
unmittelbar vor der vorhergehenden Zeile ein.

#endif // !defined(AFX_REDIRECTSTDOUT_H__E586D748_1CF4_11D4_8B97_00001CD5E4D1__INCLUDED_)

/////////////////////////////////////////////////////////////////////////////
// Copyright:
// Uwe Kotyczka <uwe.ko...@web.de>
// created: April 2000
//
/////////////////////////////////////////////////////////////////////////////
// RedirectStdout.cpp: Implementierung der Klasse CRedirectStdout.
//
#include "StdAfx.h"
#include "RedirectStdout.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
CRedirectStdout::CRedirectStdout()
{
m_pReadThread = NULL;

m_hStdoutWrite = NULL;
m_hStdoutRead = NULL;
m_hStdoutSave = NULL;

StartRedirect();
}

CRedirectStdout::~CRedirectStdout()
{
EndRedirect();
}

#define BUFSIZE 256

UINT CRedirectStdout::ReadPipeThreadProc(LPVOID pParam)
{
DWORD dwRead;
TCHAR chBuf[BUFSIZE+1];
CRedirectStdout* pRedirect = (CRedirectStdout*)pParam;

while (TRUE)
{
if (!ReadFile(pRedirect->m_hStdoutRead, chBuf,
BUFSIZE*sizeof(TCHAR), &dwRead, NULL) || dwRead == 0)
{
DWORD dwError = GetLastError();
if (dwError == ERROR_BROKEN_PIPE || dwError ==
ERROR_INVALID_HANDLE)
break;
else
ASSERT(FALSE);
}
chBuf[dwRead/sizeof(TCHAR)] = _T('\0');
TRACE0(chBuf);
}
pRedirect->m_pReadThread = NULL;
return 0;
}

BOOL CRedirectStdout::StartRedirect()
{
HANDLE hStdoutReadTmp;
SECURITY_ATTRIBUTES saAttr;

// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

// The steps for redirecting this process's STDOUT:
// 1. Save current STDOUT, to be restored later.
// 2. Create anonymous pipe to be STDOUT for child process.
// 3. Set STDOUT to be write handle of the pipe.
// 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle.
// 5. Remove buffering so that output is written to the pipe
// immediately.

// Save the handle to the current STDOUT.
m_hStdoutSave = GetStdHandle(STD_OUTPUT_HANDLE);

// Create a pipe for STDOUT.
if (!CreatePipe(&hStdoutReadTmp, &m_hStdoutWrite, &saAttr, 0))
{
TRACE0(_T("Stdout pipe creation failed\n"));
return FALSE;
}

// Set a write handle to the pipe to be STDOUT.
if (!SetStdHandle(STD_OUTPUT_HANDLE, m_hStdoutWrite))
{
TRACE0(_T("Redirecting Stdout failed\n"));
return FALSE;
}

// Create noninheritable read handle and close the inheritable read
handle.
HANDLE hProcess = GetCurrentProcess();
if (!DuplicateHandle(hProcess, hStdoutReadTmp,
hProcess, &m_hStdoutRead,
0, FALSE, DUPLICATE_SAME_ACCESS))
{
TRACE0(_T("DuplicateHandle failed\n"));
return FALSE;
}
VERIFY(CloseHandle(hStdoutReadTmp));

// start worker thread
ASSERT(m_pReadThread == NULL);
m_pReadThread =
AfxBeginThread(ReadPipeThreadProc, this,
THREAD_PRIORITY_BELOW_NORMAL);
if (!m_pReadThread)
{
TRACE0(_T("Cannot start read-redirect thread!\n"));
return FALSE;
}

// no buffering
int hCrt = _open_osfhandle((long) GetStdHandle(STD_OUTPUT_HANDLE),
_O_TEXT);
FILE* hf = _fdopen(hCrt, "w");
*stdout = *hf;
setvbuf(stdout, NULL, _IONBF, 0);

return TRUE;
}

BOOL CRedirectStdout::EndRedirect()
{
BOOL bRet = TRUE;

// restore the saved STDOUT.
if (!SetStdHandle(STD_OUTPUT_HANDLE, m_hStdoutSave))
{
TRACE0(_T("Re-redirecting Stdout failed\n"));
bRet = FALSE;
}
VERIFY(CloseHandle(m_hStdoutWrite));
VERIFY(CloseHandle(m_hStdoutRead));

// Wait until worker thread has finished itself
while (TRUE)
{
if (m_pReadThread == NULL)
break;

TRACE0("CRedirectStdout: Waiting for worker thread to finish...\n");
Sleep(1);
}
return bRet;
}
#endif // _DEBUG

HTH

Gernot Frisch

unread,
Oct 21, 2002, 10:01:30 AM10/21/02
to
Er, sorry. How to use your class? Do I subclass it like:

CMyEdit : public CEdit : public CReditectStdout
{
};

or how to do this? It's rather interesting: How to fill a CRichEdit/Cedit
with info from a console program. Really an interesting issue to me. I never
thought it would be possible at all...

Thank you,
Gernot.

"Uwe Kotyczka" <uwe.ko...@web.de> schrieb im Newsbeitrag
news:4cd8ac7a.02102...@posting.google.com...

Ted Ferenc

unread,
Oct 22, 2002, 6:17:09 AM10/22/02
to
Here are a couple of classes I created for a prog I wrote to run consloe
apps and redirect the output to an Edit control. I had planned to place the
prog on the net as freeware, but have not got around to it, I may do in a
few days time.

download them from http://ndrw.co.uk/download/source
.cpp and .h CSpawnGUIProg and CSpawn

They were written for my own use, hopefully you can adapt them easily.

// Derive class from CSpawnGUIProg called CSpawn create methods setup
and OutputData
CSpawn spawn;
// Handle to Edit window
spawn.setUp(hWndEdit);

if(spawn.spawnRedirectOutput("MyConsoleProg") != ERROR_SUCCESS)
report error;


Ted Ferenc
This address used is maintained only for newsgroup posting.
Mail sent there may not be read by me for several days.

"Ted Ferenc" <tedf...@hotmail.com> wrote in message
news:aounup$q6j7r$1...@ID-27390.news.dfncis.de...

Jussi Jumppanen

unread,
Oct 22, 2002, 7:09:05 AM10/22/02
to
Ted Ferenc wrote:
>
> have a look at MSDN article.

>
> HOWTO: Spawn Console Processes with Redirected Standard Handles
> ID: Q190351

And if your application needs to also work for Windows 95, 98
and ME then this link might also help:

INFO: Redirection Issues on Windows 95 MS-DOS Applications
http://support.microsoft.com/support/kb/articles/q150/9/56.asp

Jussi Jumppanen
Author of: Zeus for Windows, Win32 (Brief, Emacs, etc) FTP Text Editor
"The C/C++, Java, HTML, FTP, Python, PHP, Perl programmer's editor"
Home Page: http://www.zeusedit.com

Uwe Kotyczka

unread,
Oct 22, 2002, 11:07:46 AM10/22/02
to
"Gernot Frisch" <Gernot...@no.spam.Dream-D-Sign.de> wrote in message news:<ap1137$q8ks6$1...@ID-37212.news.dfncis.de>...

> Er, sorry. How to use your class? Do I subclass it like:
>
> CMyEdit : public CEdit : public CReditectStdout
> {
> };
>
> or how to do this? It's rather interesting: How to fill a CRichEdit/Cedit
> with info from a console program. Really an interesting issue to me. I never
> thought it would be possible at all...
>
> Thank you,
> Gernot.

To use "CReditectStdout" you only need an instance of it.
Like this in your GUI app:
printf("Message 1 (not redirected)");
CReditectStdout r;
printf("Message 2 (redirected)");
When "r" goes out of scope it's destructor will be called
and consequently redirection ends.

You have to replace the "TRACE0(chBuf);" by something that prints "chBuf"
to your edit control. For example you could add a pointer to the edit control
as a member of the class. (Of course you have to initialize that pointer
correctly, say in the constructor.)

HTH

Johnny

unread,
Oct 23, 2002, 6:09:07 PM10/23/02
to

"Ted Ferenc" <tedf...@hotmail.com> ha scritto nel messaggio
news:ap38jf$r8qm4$1...@ID-27390.news.dfncis.de...

> Here are a couple of classes I created for a prog I wrote to run consloe
> apps and redirect the output to an Edit control. I had planned to place
the
> prog on the net as freeware, but have not got around to it, I may do in a
> few days time.
>
> download them from http://ndrw.co.uk/download/source
> .cpp and .h CSpawnGUIProg and CSpawn
>
> They were written for my own use, hopefully you can adapt them easily.

Thanks a lot!
Bye
John


0 new messages