Author: Tim Foden
Date: 11:58:14 04/05/02
Go up one level in this thread
On April 05, 2002 at 13:58:17, Roy Eassa wrote:
>I understand that it reads stdin. I was wondering if there was a way for
>another app to "send" something that, to Chest, looked like it was coming from
>stdin. This question is aimed at those who are experienced with programming
>tricks in Windows and/or DOS.
Yes it is possible. Under Win32 you follow the following procedure.
1. Save your current processes stdin, stdout and stderr.
2. Replace your stdin, stdout and stderr with pipes.
3. Create the child process, inheriting handles.
4. Restore your saved stdin, stdout and stderr.
5. Communicate with the child process using your end of the pipes.
Cheers, Tim.
~~~~~~~~~~~~~~~~~
NB: I have some code that does this (irrelevent code snipped out)...
class CEngine
{
public:
bool Open();
bool SetupPipe( int which )
private:
enum { cHandleStdin, cHandleStdout, cHandleStderr };
private:
CString m_workingDir;
CString m_command;
CStringArray m_args;
bool m_isOpen;
PROCESS_INFORMATION m_processInfo;
HANDLE m_hSaved[3];
HANDLE m_hChild[3];
};
bool CEngine::SetupPipe( int which )
{
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 child process's STDOUT:
// 1. Save current STDOUT, to be restored later.
// 2. Create anonymous pipe to be STDOUT for child process.
// 3. Set STDOUT of the parent process to be write handle to
// the pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle.
// get Window handle enum
DWORD winStd[3] = { STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE };
DWORD winWhich = winStd[which];
// Save the handle to the current STDOUT.
m_hSaved[which] = GetStdHandle(winWhich);
// Create a pipe for the child process's STDOUT.
HANDLE hRead, hWrite;
if( !CreatePipe(&hRead, &hWrite, &saAttr, 0) )
return false;
// if we are creating a handle for STDIN, we swap the read and write
// handles around now
if( which == cHandleStdin )
{
HANDLE hTemp = hRead;
hRead = hWrite;
hWrite = hTemp;
}
// setup the standard handle to be inherited by the child process
if( !SetStdHandle(winWhich, hWrite) )
return false;
// Create noninheritable handle and close the inheritable handle.
HANDLE hReadDup;
if( !DuplicateHandle(GetCurrentProcess(), hRead, GetCurrentProcess(),
&hReadDup, 0, false, DUPLICATE_SAME_ACCESS) )
return false;
CloseHandle( hRead );
// save the handle we will used to communicate with the child process
m_hChild[which] = hReadDup;
return true;
}
bool CEngine::Open()
{
Close();
CString application;
application = m_command;
for( int i = 0; i < m_args.GetSize(); i++ )
application += " \"" + m_args[i] + "\"";
if( !SetupPipe(cHandleStdin) )
return false;
if( !SetupPipe(cHandleStdout) )
return false;
if( !SetupPipe(cHandleStderr) )
return false;
STARTUPINFO si;
memset( &si, 0, sizeof(si) );
si.cb = sizeof(si);
memset( &m_processInfo, 0, sizeof(m_processInfo) );
if( !CreateProcess(application, NULL, NULL, NULL, true,
NORMAL_PRIORITY_CLASS, NULL,
m_workingDir, &si, &m_processInfo) )
{
return false;
}
SetStdHandle( STD_INPUT_HANDLE, m_hSaved[cHandleStdin] );
SetStdHandle( STD_OUTPUT_HANDLE, m_hSaved[cHandleStdout] );
SetStdHandle( STD_ERROR_HANDLE, m_hSaved[cHandleStderr] );
m_isOpen = true;
m_readBufferUsed = 0;
return true;
}
void CEngine::Close()
{
if( !m_isOpen )
return;
Send("quit\n");
WaitForSingleObject( m_processInfo.hProcess, 10000 );
CloseHandle( m_processInfo.hThread );
CloseHandle( m_processInfo.hProcess );
m_isOpen = false;
}
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.