Discussion:
MFC: concurrent display of console output on GUI edit box.
(too old to reply)
kon
2012-03-03 09:27:32 UTC
Permalink
I want to develop an application in MFC which could start a lengthy
console process and give its output concurrently on a text area of
32bit windows application.
I used pipes, but it display the output only after the process has
terminated. I tried _popen, it works for console based application,
but not compatible with win32 application.
I AM FACING THE PROBLEM THAT OUTPUT IS DISPLAYED ONLY AFTER CONSOLE
PROCESS ENDS.
Is there any way I could do this.. Here's my code. Thanks in advance.

void CAppMgr_BackupsDlg::ExecuteExternalFile(CString csExeName,
CString csArguments)
{

CString csExecute;
csExecute=csExeName + " " + csArguments;

SECURITY_ATTRIBUTES secattr;
ZeroMemory(&secattr,sizeof(secattr));
secattr.nLength = sizeof(secattr);
secattr.bInheritHandle = TRUE;

HANDLE rPipe, wPipe;

//Create pipes to write and read data
CreatePipe(&rPipe,&wPipe,&secattr,0);

STARTUPINFO sInfo;
ZeroMemory(&sInfo,sizeof(sInfo));
PROCESS_INFORMATION pInfo;
ZeroMemory(&pInfo,sizeof(pInfo));
sInfo.cb=sizeof(sInfo);
sInfo.dwFlags=STARTF_USESTDHANDLES;
sInfo.hStdInput=NULL;
sInfo.hStdOutput=wPipe;
sInfo.hStdError=wPipe;
char command[1024];
strcpy(command, csExecute.GetBuffer(csExecute.GetLength()));

//Create the process here.
CreateProcess(0, command,0,0,TRUE,
NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
CloseHandle(wPipe);

//now read the output pipe here.
char buf[100];
DWORD reDword;
CString m_csOutput,csTemp;
BOOL res;
do
{
res=::ReadFile(rPipe,buf,100,&reDword,0);
csTemp=buf;
m_csOutput=csTemp.Left(reDword);
DisplayToTextArea(m_csOutput);
}
while(res);
}
paolob
2012-03-07 08:04:50 UTC
Permalink
//-----------------------------------------------------------------------------
// Calling process...
//-----------------------------------------------------------------------------
#include "process.h"

typedef void (__cdecl * TSend_Output)(const char * );

// remember to implement this function... ;-) for display output
extern TSend_Output Send_StdOutput ;
extern TSend_Output Send_StdError ;

void Read_OutPut( HANDLE h, TSend_Output Send_Output )
{
char Buf[512];

unsigned long avail=0; //bytes available
do
{
PeekNamedPipe(h, Buf, sizeof(Buf)-1,NULL, &avail,NULL);

//check to see if there is any data to read from stdout
if( avail ) // ce ne รจ !!!!
{
unsigned long letti=0; //bytes available
if( ReadFile( h, Buf, min(avail,sizeof(Buf)-1), &letti,
NULL) )
{
Buf[letti] =0;
TRACE0(Buf);
if(Send_Output) Send_Output(Buf);
}
}
} while(avail);
}

bool CallProcess( const CString & cmd )
{
try
{
char buf[1024];
strcpy( buf, cmd);

PROCESS_INFORMATION pInfo;
STARTUPINFO sInfo;
memset(&sInfo,0,sizeof(STARTUPINFO));
memset(&pInfo,0,sizeof(PROCESS_INFORMATION));

sInfo.cb = sizeof(STARTUPINFO);

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = NULL;

HANDLE hIRead=NULL, hIWrite=NULL;
HANDLE hORead=NULL, hOWrite=NULL;
HANDLE hERead=NULL, hEWrite=NULL;

BOOL retpipeI =retpipeI = CreatePipe(&hIRead, &hIWrite, &sa,
NULL);
BOOL retpipeO =retpipeO = CreatePipe(&hORead, &hOWrite, &sa,
NULL);
BOOL retpipeE =retpipeE = CreatePipe(&hERead, &hEWrite, &sa,
NULL);

BOOL cp=FALSE;

if( retpipeI && retpipeO && retpipeE )
{
HANDLE hProcess = GetCurrentProcess();

DuplicateHandle(hProcess, hIRead , hProcess,
&sInfo.hStdInput , 0, TRUE, DUPLICATE_SAME_ACCESS |
DUPLICATE_CLOSE_SOURCE);
DuplicateHandle(hProcess, hOWrite, hProcess,
&sInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS |
DUPLICATE_CLOSE_SOURCE);
DuplicateHandle(hProcess, hEWrite, hProcess,
&sInfo.hStdError , 0, TRUE, DUPLICATE_SAME_ACCESS |
DUPLICATE_CLOSE_SOURCE);
sInfo.dwFlags = STARTF_USESTDHANDLES|
STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_HIDE;
cp = CreateProcess(NULL,
buf,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&sInfo,
&pInfo);
}
else
{
sInfo.dwFlags = 0;
cp = CreateProcess(NULL,
buf,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&sInfo,
&pInfo);
}

if( ! cp )
return false;

Sleep( 200 );

FILETIME CreationTime; // when the process was created
FILETIME ExitTime; // when the process exited
FILETIME KernelTime; // time the process has spent in kernel
mode
ULARGE_INTEGER UserTime; // time the process has spent in
user mode
ULARGE_INTEGER LastUserTime; // time the process has spent
in user mode
LastUserTime.QuadPart=0;

unsigned TimeDead = 0; //
const unsigned TimeOut = 60000; // un minuto
const unsigned gap = 10;

// Give the process time to execute and finish
DWORD ret;
do
{
ret = WaitForSingleObject(pInfo.hProcess, gap);

if( GetProcessTimes( pInfo.hProcess, &CreationTime,
&ExitTime, &KernelTime, (FILETIME *)&UserTime ) )
{
ULARGE_INTEGER dif;
dif.QuadPart = UserTime.QuadPart -
LastUserTime.QuadPart;
unsigned div=1000;
if( unsigned(dif.QuadPart/div) )
{
LastUserTime.QuadPart = UserTime.QuadPart;
TimeDead = 0; // ci ripenso, ma non troppo...
}
else
{
TimeDead += gap;
}
}

if( ret == WAIT_TIMEOUT && retpipeI && retpipeO &&
retpipeE )
{
Read_OutPut(hORead, Send_StdOutput );
Read_OutPut(hERead, Send_StdError );
}
}
while( ret == WAIT_TIMEOUT );

TRACE1("\n GetLastError=%d", GetLastError() );

if( retpipeI && retpipeO && retpipeE )
{
Read_OutPut(hORead, Send_StdOutput );
Read_OutPut(hERead, Send_StdError );
CloseHandle(hIWrite);
CloseHandle(hORead);
CloseHandle(hERead);
CloseHandle(sInfo.hStdInput );
CloseHandle(sInfo.hStdOutput);
CloseHandle(sInfo.hStdError );
}

DWORD exitCode;
if (GetExitCodeProcess(pInfo.hProcess, &exitCode))
{
switch(exitCode)
{
case STILL_ACTIVE:
assert(0); // come e' potuto succedere???
break;

default:
break;
}
}
CloseHandle(pInfo.hProcess);
CloseHandle(pInfo.hThread);
}
catch(...)
{
return false;
}
return true;
}

Loading...