? | MSDN里面有一些文档可以看看,方法是利用CreateProcess的 LPSTARTUPINFO 参数,
设置dwFlags为STARTF_USESTDHANDLES:
然后自定义:
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
三个流句柄。
这些句柄可以用CreatePipe创建的匿名管道句柄代替:
BOOL CreatePipe(
PHANDLE hReadPipe, // read handle
PHANDLE hWritePipe, // write handle
LPSECURITY_ATTRIBUTES lpPipeAttributes, // security attributes
DWORD nSize // pipe size
);
其中hStdOutput,hStdError传给hWritePipe,hStdInput传给hReadPipe,然后把管道的另一端的句柄保存起来。就可以用ReadFile/WriteFile从这些句柄读取/写入控制台程序的输出/输入。
要注意的是这些句柄的继承性,调用CreateProcess时注意设置BOOL bInheritHandles = TRUE,使它可以继承主进程的句柄。调用CreatePipe要设置LPSECURITY_ATTRIBUTES lpPipeAttributes参数使Pipe的句柄能够被继承。
此外,这样使CreatePipe创建的两个句柄都可以被继承了,所以要调用DuplicateHandle把不需要传入子进程的句柄设置为不可继承。不然子进程拥有了另一个句柄但是不会调用Closehandle减少引用记数,会导致Pipe不能被在使用完毕后被撤消。
此外注意关闭所有使用过的内核对象句柄。
以下是MSDN的一个例子:
- INHERIT.C
-
-
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define USESTDHANDLES
- int main(int argc, char *argv[])
- {
- char chReadBuffer[64];
- BOOL bSuccess;
- int j;
- HANDLE hOutFile;
-
- HANDLE hReadPipe, hWritePipe, hWritePipe2;
- char szArgs[256];
- char *p;
- DWORD cchReadBuffer;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- SECURITY_ATTRIBUTES saPipe;
- OSVERSIONINFO os;
-
- os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-
- if ( GetVersionEx(&os) )
- {
- if( os.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS &
- os.dwPlatformId != VER_PLATFORM_WIN32_NT)
- {
- MessageBox( NULL,
- "This sample application can only run on Windows NT and Windows 95./n
- This application will now terminate.",
- "Inherit",
- MB_OK | MB_ICONSTOP | MB_SETFOREGROUND );
- return( 1 );
- }
- }
- else
- {
- MessageBox( NULL,
- "Unable to test for OS version.",
- "Inherit Error",
- MB_OK | MB_ICONSTOP | MB_SETFOREGROUND );
- return( 1 );
- }
- if (argc < 3)
- {
- puts("format: inherit <trace file> <command to execute>");
- puts("trace file is the name of the file where the stdout");
- puts("and stderr of command will be redirected/n");
- puts("command to execute is command line of the function");
- puts("you wish to perform./n");
- puts("Examples:/n");
- puts(" inherit trace.txt chkdsk d:");
- puts(" inherit trace.txt nmake /f foo.mak");
- return(1);
- }
-
- hOutFile = CreateFile(argv[1],
- GENERIC_WRITE,
- FILE_SHARE_READ,
- NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- PERR(hOutFile != INVALID_HANDLE_VALUE, "CreateFile");
-
- saPipe.nLength = sizeof(SECURITY_ATTRIBUTES);
- saPipe.lpSecurityDescriptor = NULL;
-
-
- saPipe.bInheritHandle = TRUE;
-
-
- bSuccess = CreatePipe(&hReadPipe,
- &hWritePipe,
- &saPipe,
- 0);
- PERR(bSuccess, "CreatePipe");
-
- bSuccess = DuplicateHandle(GetCurrentProcess(),
- hReadPipe,
- GetCurrentProcess(),
- NULL,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
- PERR(bSuccess, "DuplicateHandle");
-
-
-
- bSuccess = DuplicateHandle(GetCurrentProcess(),
- hWritePipe,
- GetCurrentProcess(),
- &hWritePipe2,
- 0,
- TRUE,
- DUPLICATE_SAME_ACCESS);
- PERR(bSuccess, "DuplicateHandle");
-
-
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
-
-
- memset(szArgs, 0, sizeof(szArgs));
- strcpy(szArgs, argv[2]);
- if (strchr(szArgs, '.') == NULL)
- strcat(szArgs, ".exe");
- strcat(szArgs, " ");
- p = strchr(szArgs, 0);
- for (j = 3; j < argc; j++)
- {
- strcat(p, argv[j]);
-
- strcat(p, " ");
- }
- #ifdef USESTDHANDLES
-
-
- si.hStdInput = hWritePipe2;
- si.hStdOutput = hWritePipe;
- si.hStdError = hWritePipe2;
- si.dwFlags = STARTF_USESTDHANDLES;
- #else
-
- bSuccess = SetStdHandle(STD_INPUT_HANDLE, hWritePipe2);
- PERR(bSuccess, "SetStdHandle");
- bSuccess = SetStdHandle(STD_OUTPUT_HANDLE, hWritePipe);
- PERR(bSuccess, "SetStdHandle");
- bSuccess = SetStdHandle(STD_ERROR_HANDLE, hWritePipe2);
- PERR(bSuccess, "SetStdHandle");
- bSuccess = DuplicateHandle(GetCurrentProcess(),
- GetStdHandle(STD_INPUT_HANDLE),
- GetCurrentProcess(),
- NULL,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
- PERR(bSuccess, "DuplicateHandle");
- #endif
-
-
-
- bSuccess = CreateProcess(NULL,
- szArgs,
- NULL,
- NULL,
- TRUE,
- 0,
- NULL,
- NULL,
- &si,
- π);
- PERR(bSuccess, "CreateProcess");
-
-
-
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
-
-
-
- bSuccess = CloseHandle(hWritePipe);
- PERR(bSuccess, "CloseHandle");
- bSuccess = CloseHandle(hWritePipe2);
- PERR(bSuccess, "CloseHandle");
-
-
- for (;;)
- {
- bSuccess = ReadFile(hReadPipe,
- chReadBuffer,
- sizeof(chReadBuffer),
- &cchReadBuffer,
- NULL);
- if (!bSuccess && (GetLastError() == ERROR_BROKEN_PIPE))
- break;
-
- PERR(bSuccess, "ReadFile");
- if (bSuccess && cchReadBuffer)
- {
-
- bSuccess = WriteFile(hOutFile,
- chReadBuffer,
- cchReadBuffer,
- &cchReadBuffer,
- NULL);
- PERR(bSuccess, "WriteFile");
-
-
- printf("%.*s", cchReadBuffer, chReadBuffer);
- }
- }
-
- CloseHandle(hOutFile);
- CloseHandle(hReadPipe);
- return(0);
- }
- void PERR(BOOL bSuccess, char * api)
- {
- DWORD dwError;
- TCHAR szMsgBuf[500];
-
- if (!(bSuccess))
- {
- dwError = GetLastError();
- printf("/nFile:%s/nError occured in %s on line %d/n", __FILE__, api, __LINE__);
- FormatMessage(
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- dwError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- szMsgBuf,
- 500,
- NULL );
-
- printf("/nError:(%ld)%s ", dwError, szMsgBuf);
- }
- }
-
|