CreatePipe创建的是匿名管道,匿名管道数据只能单向流动,所以如果要能对子进程输入数据也能读出执行结果,就是创建两个匿名管道了,一个用来输
入数据到子进程,一个用来从子进程中读出数据。CreatePipe分别有两个HANDLE的读写句柄,把这两个管道的读写句柄分别用在
CreateProcess()的STARTINFO的参数上,然后创建进程就可以了。
- HANDLE hSTDINWrite,hSTDINRead,hSTDINWriteup; //用于重定向子进程输入的句柄
-
HANDLE hSTDOUTWrite,hSTDOUTRead, hSTDOUTReadup; //用于重定向子进程输出的句柄
-
SECURITY_ATTRIBUTES sa;
-
-
sa.bInheritHandle = true;
-
sa.lpSecurityDescriptor = NULL;
-
sa.nLength = sizeof(sa);
-
//创建子进程输出匿名管道
-
if( !CreatePipe(&hSTDOUTRead, &hSTDOUTWrite, &sa,0) )
-
{
-
AfxMessageBox( "Create STDOUT pipe failed ");
-
return 0;
-
}
-
-
if( !DuplicateHandle( ::GetCurrentProcess(), hSTDOUTRead, ::GetCurrentProcess(), &hSTDOUTReadup, 0, false,DUPLICATE_SAME_ACCESS) )
-
{
-
AfxMessageBox( "DuplicateHandle failed ");
-
return 0;
-
}
-
::CloseHandle( hSTDOUTRead );
-
-
//创建子进程输入匿名管道
-
if( !CreatePipe(&hSTDINRead, &hSTDINWrite, &sa,0) )
-
{
-
AfxMessageBox( "Create STDIN pipe failed ");
-
return 0;
-
}
-
if( !DuplicateHandle( ::GetCurrentProcess(), hSTDINWrite, ::GetCurrentProcess(), &hSTDINWriteup, 0, false,DUPLICATE_SAME_ACCESS) )
-
{
-
AfxMessageBox( "DuplicateHandle failed ");
-
return 0;
-
}
-
::CloseHandle( hSTDINWrite );
-
-
-
CTestpipeDlg *pDlg = (CTestpipeDlg *)lpData;
-
PROCESS_INFORMATION pi;
-
STARTUPINFO si;
-
ZeroMemory( &si, sizeof(si));
-
-
-
si.cb = sizeof(STARTUPINFO);
-
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-
si.wShowWindow = SW_HIDE;
-
si.hStdInput = hSTDINRead; //重定向子进程输入
-
si.hStdOutput = hSTDOUTWrite; //重定向子进程输入
-
si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
-
if( !::CreateProcess(NULL, (char *)(LPCSTR)pDlg-> m_strCmd, NULL, NULL, true, 0,NULL,NULL,&si,&pi) )
-
{
-
AfxMessageBox( "create process failed ");
-
return 0;
-
}
-
-
char strData[1024];
-
const char *strIn = "2 3\n2 4\n4 67\n0 0\n ";
-
pDlg-> m_strOut = " ";
-
::SendMessage(pDlg-> m_hWnd, WM_UPDATE_MYDATA,0,0);
-
DWORD dwBytes = 0;
-
-
::CloseHandle( hSTDINRead );
-
//将数据写入子进程,我在子进程中进行的是对strIn的每两个数进行相加操作
-
::WriteFile( hSTDINWriteup, strIn, strlen(strIn), &dwBytes, NULL);
-
-
//在调用ReadFile前必须关闭该句柄,否则由于父进程的管道写入端有未关闭的Write句柄,ReadFile最后无法返回0
-
::CloseHandle( hSTDOUTWrite );
-
-
//从子进程中读出执行结果
-
while( ::ReadFile( hSTDOUTReadup, strData, sizeof(strData), &dwBytes, NULL) )
-
{
-
strData[dwBytes] = '\0 ';
-
pDlg-> m_strOut += strData;
-
::SendMessage(pDlg-> m_hWnd, WM_UPDATE_MYDATA,0,0);
-
}
-
-
-
::WaitForSingleObject( pi.hProcess, INFINITE);
-
::CloseHandle( hSTDOUTReadup );
-
::CloseHandle( hSTDINWriteup );
-
::CloseHandle(pi.hProcess);
-
::CloseHandle(pi.hThread);
- //网上抄来的,供参考
-
/*++
-
-
Copyright (c) 1998 Microsoft Corporation
-
-
Module Name:
-
-
Redirect.c
-
-
Description:
-
This sample illustrates how to spawn a child console based
-
application with redirected standard handles.
-
-
The following import libraries are required:
-
user32.lib
-
-
Dave McPherson (davemm) 11-March-98
-
-
--*/
-
-
#include <windows.h>
-
-
void DisplayError(char *pszAPI);
-
void ReadAndHandleOutput(HANDLE hPipeRead);
-
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
-
HANDLE hChildStdIn,
-
HANDLE hChildStdErr);
-
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam);
-
-
HANDLE hChildProcess = NULL;
-
HANDLE hStdIn = NULL; // Handle to parents std input.
-
BOOL bRunThread = TRUE;
-
-
-
void main ()
-
{
-
HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
-
HANDLE hInputWriteTmp,hInputRead,hInputWrite;
-
HANDLE hErrorWrite;
-
HANDLE hThread;
-
DWORD ThreadId;
-
SECURITY_ATTRIBUTES sa;
-
-
-
// Set up the security attributes struct.
-
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
-
sa.lpSecurityDescriptor = NULL;
-
sa.bInheritHandle = TRUE;
-
-
-
// Create the child output pipe.
-
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
-
DisplayError( "CreatePipe ");
-
-
-
// Create a duplicate of the output write handle for the std error
-
// write handle. This is necessary in case the child application
-
// closes one of its std output handles.
-
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
-
GetCurrentProcess(),&hErrorWrite,0,
-
TRUE,DUPLICATE_SAME_ACCESS))
-
DisplayError( "DuplicateHandle ");
-
-
-
// Create the child input pipe.
-
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
-
DisplayError( "CreatePipe ");
-
-
-
// Create new output read handle and the input write handles. Set
-
// the Properties to FALSE. Otherwise, the child inherits the
-
// properties and, as a result, non-closeable handles to the pipes
-
// are created.
-
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
-
GetCurrentProcess(),
-
&hOutputRead, // Address of new handle.
-
0,FALSE, // Make it uninheritable.
-
DUPLICATE_SAME_ACCESS))
-
DisplayError( "DupliateHandle ");
-
-
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
-
GetCurrentProcess(),
-
&hInputWrite, // Address of new handle.
-
0,FALSE, // Make it uninheritable.
-
DUPLICATE_SAME_ACCESS))
-
DisplayError( "DupliateHandle ");
-
-
-
// Close inheritable copies of the handles you do not want to be
-
// inherited.
-
if (!CloseHandle(hOutputReadTmp)) DisplayError( "CloseHandle ");
-
if (!CloseHandle(hInputWriteTmp)) DisplayError( "CloseHandle ");
-
-
-
// Get std input handle so you can close it and force the ReadFile to
-
// fail when you want the input thread to exit.
-
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==
-
INVALID_HANDLE_VALUE )
-
DisplayError( "GetStdHandle ");
-
-
PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite);
-
-
-
// Close pipe handles (do not continue to modify the parent).
-
// You need to make sure that no handles to the write end of the
-
// output pipe are maintained in this process or else the pipe will
-
// not close when the child process exits and the ReadFile will hang.
-
if (!CloseHandle(hOutputWrite)) DisplayError( "CloseHandle ");
-
if (!CloseHandle(hInputRead )) DisplayError( "CloseHandle ");
-
if (!CloseHandle(hErrorWrite)) DisplayError( "CloseHandle ");
-
-
-
// Launch the thread that gets the input and sends it to the child.
-
hThread = CreateThread(NULL,0,GetAndSendInputThread,
-
(LPVOID)hInputWrite,0,&ThreadId);
-
if (hThread == NULL) DisplayError( "CreateThread ");
-
-
-
// Read the child 's output.
-
ReadAndHandleOutput(hOutputRead);
-
// Redirection is complete
-
-
-
// Force the read on the input to return by closing the stdin handle.
-
if (!CloseHandle(hStdIn)) DisplayError( "CloseHandle ");
-
-
-
// Tell the thread to exit and wait for thread to die.
-
bRunThread = FALSE;
-
-
if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
-
DisplayError( "WaitForSingleObject ");
-
-
if (!CloseHandle(hOutputRead)) DisplayError( "CloseHandle ");
-
if (!CloseHandle(hInputWrite)) DisplayError( "CloseHandle ");
-
}
-
-
-
///////////////////////////////////////////////////////////////////////
-
// PrepAndLaunchRedirectedChild
-
// Sets up STARTUPINFO structure, and launches redirected child.
-
///////////////////////////////////////////////////////////////////////
-
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
-
HANDLE hChildStdIn,
-
HANDLE hChildStdErr)
-
{
-
PROCESS_INFORMATION pi;
-
STARTUPINFO si;
-
-
// Set up the start up info struct.
-
ZeroMemory(&si,sizeof(STARTUPINFO));
-
si.cb = sizeof(STARTUPINFO);
-
si.dwFlags = STARTF_USESTDHANDLES;
-
si.hStdOutput = hChildStdOut;
-
si.hStdInput = hChildStdIn;
-
si.hStdError = hChildStdErr;
-
// Use this if you want to hide the child:
-
// si.wShowWindow = SW_HIDE;
-
// Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
-
// use the wShowWindow flags.
-
-
-
// Launch the process that you want to redirect (in this case,
-
// Child.exe). Make sure Child.exe is in the same directory as
-
// redirect.c launch redirect from a command line to prevent location
-
// confusion.
-
if (!CreateProcess(NULL, "d:\\winnt\\system32\\cmd.exe ",NULL,NULL,TRUE,
-
CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
-
DisplayError( "CreateProcess ");
-
-
-
// Set global child process handle to cause threads to exit.
-
hChildProcess = pi.hProcess;
-
-
-
// Close any unnecessary handles.
-
if (!CloseHandle(pi.hThread)) DisplayError( "CloseHandle ");
-
}
-
-
-
///////////////////////////////////////////////////////////////////////
-
// ReadAndHandleOutput
-
// Monitors handle for input. Exits when child exits or pipe breaks.
-
///////////////////////////////////////////////////////////////////////
-
void ReadAndHandleOutput(HANDLE hPipeRead)
-
{
-
CHAR lpBuffer[256];
-
DWORD nBytesRead;
-
DWORD nCharsWritten;
-
-
while(TRUE)
-
{
-
if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
-
&nBytesRead,NULL) || !nBytesRead)
-
{
-
if (GetLastError() == ERROR_BROKEN_PIPE)
-
break; // pipe done - normal exit path.
-
else
-
DisplayError( "ReadFile "); // Something bad happened.
-
}
-
-
// Display the character read on the screen.
-
if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,
-
nBytesRead,&nCharsWritten,NULL))
-
DisplayError( "WriteConsole ");
-
}
-
}
- ///////////////////////////////////////////////////////////////////////
-
// GetAndSendInputThread
-
// Thread procedure that monitors the console for input and sends input
-
// to the child process through the input pipe.
-
// This thread ends when the child application exits.
-
///////////////////////////////////////////////////////////////////////
-
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
-
{
-
CHAR read_buff[256];
-
DWORD nBytesRead,nBytesWrote;
-
HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
-
-
// Get input from our console and send it to child through the pipe.
-
while (bRunThread)
-
{
-
if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL))
-
DisplayError( "ReadConsole ");
-
-
read_buff[nBytesRead] = '\0 '; // Follow input with a NULL.
-
-
if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))
-
{
-
if (GetLastError() == ERROR_NO_DATA)
-
break; // Pipe was closed (normal exit path).
-
else
-
DisplayError( "WriteFile ");
-
}
-
}
-
-
return 1;
-
}
-
-
-
///////////////////////////////////////////////////////////////////////
-
// DisplayError
-
// Displays the error number and corresponding message.
-
///////////////////////////////////////////////////////////////////////
-
void DisplayError(char *pszAPI)
-
{
-
LPVOID lpvMessageBuffer;
-
CHAR szPrintBuffer[512];
-
DWORD nCharsWritten;
-
-
FormatMessage(
-
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
-
NULL, GetLastError(),
-
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-
(LPTSTR)&lpvMessageBuffer, 0, NULL);
-
-
wsprintf(szPrintBuffer,
-
"ERROR: API = %s.\n error code = %d.\n message = %s.\n ",
-
pszAPI, GetLastError(), (char *)lpvMessageBuffer);
-
-
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer,
-
lstrlen(szPrintBuffer),&nCharsWritten,NULL);
-
-
LocalFree(lpvMessageBuffer);
-
ExitProcess(GetLastError());
-
}
- http://www.codeguru.com/Cpp/W-D/console/redirection/article.php/c541/
-
-
这个是可以输入的(我没有用过输入部分)
-
-
对于 DOS 程序的输出,我认为这个程序是我见过的最好的了,希望对你有用 :)
-
-
文件只需要
-
Redirect.cpp
-
Redirect.h
-
可以派生,用着很好用。
阅读(2632) | 评论(0) | 转发(1) |