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;
}
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