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

Problems using CreateProcess and CreatePipe to redirect console output

285 views
Skip to first unread message

Kirsten Chevalier

unread,
Aug 16, 2004, 9:29:42 PM8/16/04
to
Hi,
I have a console program and I want to execute other console programs
from it and display their output in the same console window. I'm using
MS Visual C++ 6.0 on Windows XP. I read the tutorial "Creating a Child
Process with Redirected Input and Output" (at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/creating_a_child_process_with_redirected_input_and_output.asp),
and wrote some code based on their example.

My code is below. The top-level function is util_ExecAndWait(), which
I invoke with a command-line string to be executed. util_ExecAndWait()
calls util_Exec(), which starts the process and returns handles for
the process itself and its input and output pipes in hProcess,
hReadPipe, and hWritePipe, then calls util_WaitFor() to wait for the
program to terminate and then display its output.

When I run the code, it executes the command successfully (I know this
because it's invoking a program that creates files and such), but none
of the output is displayed to my application's console. I know that
the command being executed does have output. When I step through it in
the debugger, I see that the first call to ReadFile in util_WaitFor()
returns FALSE, so the loop is exited on the first iteration and none
of the output is read. Can anyone see what I'm doing wrong?

Thanks,
Kirsten

int util_ExecAndWait( char* command ) {

HANDLE hProcess, hReadPipe, hWritePipe;

if( !util_Exec( command, &hProcess, &hReadPipe, &hWritePipe ) )
return -1;
else
{
return util_WaitFor( hProcess, hReadPipe, hWritePipe );
}
}

int util_Exec( char* command, LPHANDLE processId, LPHANDLE hReadPipe,
LPHANDLE hWritePipe ) {
LPPROCESS_INFORMATION procInfo;
LPSTARTUPINFO startupInfo;
int procRes;

SECURITY_ATTRIBUTES saAttr;
HANDLE hChildStdoutRd, hChildStdinRd,
hChildStdinWr, hChildStdinWrDup;
int fSuccess;

saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

// Create a pipe for the child process's STDOUT.
if (! CreatePipe(&hChildStdoutRd, hWritePipe, &saAttr, 0))
return FALSE;

// Create noninheritable read handle and close the inheritable read
// handle.

fSuccess = DuplicateHandle(GetCurrentProcess(),
hChildStdoutRd,
GetCurrentProcess(), hReadPipe , 0, FALSE,
DUPLICATE_SAME_ACCESS);
if( !fSuccess )
return FALSE;
CloseHandle(hChildStdoutRd);

// Create a pipe for the child process's STDIN.
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
return FALSE;

// 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)
return FALSE;

// Now create the child process.
procInfo = ALLOC( PROCESS_INFORMATION, 1 );
startupInfo = ALLOC( STARTUPINFO, 1 );
startupInfo->cb = sizeof(STARTUPINFO);
startupInfo->lpReserved = NULL;
startupInfo->lpDesktop = NULL;
startupInfo->lpTitle = NULL;
startupInfo->cbReserved2 = 0;
startupInfo->lpReserved2 = NULL;
startupInfo->dwFlags |= STARTF_USESTDHANDLES;
startupInfo->hStdOutput = startupInfo->hStdError = hWritePipe;
startupInfo->hStdInput = hChildStdinRd;

procRes = CreateProcess( NULL, command, NULL, NULL, TRUE, FALSE,
NULL, NULL, startupInfo, procInfo );

if( procRes == 0 ) {
debugPrint( "CreateProcess failed" );
return FALSE;
}

if( processId != NULL ) {
*processId = OpenProcess( PROCESS_ALL_ACCESS, FALSE,
procInfo->dwProcessId );
}

return TRUE;
}

int util_WaitFor( HANDLE hProcess, HANDLE hReadPipe, HANDLE hWritePipe
) {
DWORD exitCode, dwRead, dwWritten;
char chBuf[4096];
HANDLE hStdout;

if( hProcess == NULL )
return -1;
WaitForSingleObject( hProcess, INFINITE );

if( !GetExitCodeProcess( hProcess, &exitCode ) )
return -1;
CloseHandle( hProcess );
CloseHandle( hWritePipe );

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
for (;;)
{
if( !ReadFile( hReadPipe, chBuf, 4096, &dwRead,
NULL) || dwRead == 0) break;
if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))
break;
}

return exitCode;
}

Sten Westerback

unread,
Aug 17, 2004, 7:43:14 AM8/17/04
to

"Kirsten Chevalier" <catamo...@gmail.com> wrote in message
news:4683d937.04081...@posting.google.com...

> Hi,
> I have a console program and I want to execute other console programs
> from it and display their output in the same console window. I'm using
> MS Visual C++ 6.0 on Windows XP. I read the tutorial "Creating a Child
> Process with Redirected Input and Output" (at
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas
e/creating_a_child_process_with_redirected_input_and_output.asp),
> and wrote some code based on their example.
>
> My code is below. The top-level function is util_ExecAndWait(), which
> I invoke with a command-line string to be executed. util_ExecAndWait()
> calls util_Exec(), which starts the process and returns handles for
> the process itself and its input and output pipes in hProcess,
> hReadPipe, and hWritePipe, then calls util_WaitFor() to wait for the
> program to terminate and then display its output.
>

Hi

I haven't got much time for detailed study but here is a routine that works.
You may be able to use it as such... or see what's wrong with your code.

DWORD dwExecOnServer(char *p_szCmd, char **pp_szResult, DWORD dwTimeout,
char *p_szStdInData)
{ // returns process exit code (= errorlevel)
STARTUPINFO sui;
PROCESS_INFORMATION pi;
char *p_sz;
DWORD dw, dwResult;
SECURITY_ATTRIBUTES sa;
HANDLE hStdChild[2], // childs StdIn/StdOut
hStdHost[2], // hosts Readside/WriteSide
hTmp; // temporary handle
LONG lTmp;

if (pp_szResult!=NULL) *pp_szResult = NULL;
// initialize SUI
memset(&sui, 0, sizeof(STARTUPINFO)); sui.cb = sizeof(STARTUPINFO);
lTmp=InterlockedCompareExchange(&_lActiveExecutions, 0, 100000L);
if (lTmp>40) Sleep(300*lTmp); else if (lTmp>20) Sleep(5000); else if
(lTmp>10) Sleep(2000);
InterlockedIncrement(&_lActiveExecutions);
// Create NULL security attribute
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL;

// Create pipe for Us <- child process, childs's StdOut
CreatePipe(&hTmp, &hStdChild[1], &sa, 0);
DuplicateHandle(GetCurrentProcess(), hTmp,
GetCurrentProcess(), &hStdHost[0], 0,


FALSE, // not inherited
DUPLICATE_SAME_ACCESS);

CloseHandle(hTmp);

// create pipe for childs StdIn
CreatePipe(&hStdChild[0], &hTmp, &sa, 0);
DuplicateHandle(GetCurrentProcess(), hTmp,
GetCurrentProcess(), &hStdHost[1], 0,


FALSE, // not inherited
DUPLICATE_SAME_ACCESS);

CloseHandle(hTmp);
sui.wShowWindow = SW_HIDE;
sui.hStdOutput=hStdChild[1]; sui.hStdInput=hStdChild[0];
sui.hStdError=hStdChild[1];
sui.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
// Create the process
if (CreateProcess(NULL, p_szCmd, NULL, NULL, TRUE,
NORMAL_PRIORITY_CLASS, NULL, NULL, &sui, &pi) == 0)
{
InterlockedDecrement(&_lActiveExecutions);
dwResult = GetLastError();
CloseHandle(hStdHost[0]); CloseHandle(hStdHost[1]);
CloseHandle(hStdChild[0]); CloseHandle(hStdChild[1]);
p_sz=malloc(10000);
dw=sprintf(p_sz, "Fault trying SrvCmd(%s)! ErrCode:%lu. User:%s.",
p_szCmd, dwResult, p_opi->p_user->szAccount30);
p_sz=realloc(p_sz, dw+1);
if (pp_szResult !=NULL) *pp_szResult = p_sz;
return OP_EXEC_ERROR;
}
CloseHandle(pi.hThread);
if (p_szStdInData!=NULL)
{ // Provide some simulated keyboard input to the application
dw=strlen(p_szStdInData);
WriteFile(hStdHost[1], p_szStdInData, dw, &dw, NULL);
}
// Wait for completion with timeout
WaitForSingleObject(pi.hProcess, dwTimeout);
GetExitCodeProcess(pi.hProcess, &dwResult);
InterlockedDecrement(&_lActiveExecutions);
if (dwResult==STILL_ACTIVE)
{
TerminateProcess(pi.hProcess, 4711);
CloseHandle(hStdHost[0]); CloseHandle(hStdHost[1]);
CloseHandle(hStdChild[0]); CloseHandle(hStdChild[1]);
CloseHandle(pi.hProcess);
if (pp_szResult!=NULL)
{
p_sz=malloc(200); sprintf(p_sz, "%s timeout!", p_szCmd);
*pp_szResult = p_sz;
}
return OP_EXEC_ERROR;
}
CloseHandle(hStdHost[1]); CloseHandle(hStdChild[0]);
CloseHandle(hStdChild[1]);
// Read the output if we want it
if (pp_szResult!=NULL)
{
p_sz=malloc(5001);
if (hStdHost[0]==INVALID_HANDLE_VALUE || !ReadFile(hStdHost[0], p_sz,
5000, &dw, NULL))
{
dw=sprintf(p_sz, "NoData from %s!", p_szCmd);
p_sz=realloc(p_sz, dw+1);
CloseHandle(hStdHost[0]); CloseHandle(pi.hProcess);
*pp_szResult = p_sz; return dwResult;
}
p_sz=realloc(p_sz, dw+10); p_sz[dw]=0;
*pp_szResult = p_sz;
}
CloseHandle(hStdHost[0]); CloseHandle(pi.hProcess);
return dwResult;
}

- Sten


0 new messages