현재 오프라인 상태입니다. 인터넷에 다시 연결하기를 기다리고 있습니다.

이 브라우저는 지원되지 않습니다.

사이트를 사용하여 브라우저를 업데이트해야 합니다.

최신 버전의 Internet Explorer를 업데이트하세요.

콘솔 프로세스의 리디렉션된 표준 핸들이 생성 방법

중요: 본 문서는 전문 번역가가 번역한 것이 아니라 Microsoft 기계 번역 소프트웨어로 번역한 것입니다. Microsoft는 번역가가 번역한 문서 및 기계 번역된 문서를 모두 제공하므로 Microsoft 기술 자료에 있는 모든 문서를 한글로 접할 수 있습니다. 그러나 기계 번역 문서가 항상 완벽한 것은 아닙니다. 따라서 기계 번역 문서에는 마치 외국인이 한국어로 말할 때 실수를 하는 것처럼 어휘, 구문 또는 문법에 오류가 있을 수 있습니다. Microsoft는 내용상의 오역 또는 Microsoft 고객이 이러한 오역을 사용함으로써 발생하는 부 정확성, 오류 또는 손해에 대해 책임을 지지 않습니다. Microsoft는 이러한 문제를 해결하기 위해 기계 번역 소프트웨어를 자주 업데이트하고 있습니다.

190351
요약
이 문서에서는 입력 및 출력 표준 입력된 핸들에서 입력을 받는 또는 표준 출력 핸들의 출력을 보내는 자식 프로세스의 리디렉션하는 방법에 대해 설명합니다. Win32 API 응용 프로그램에서를 자식 콘솔 프로세스의 리디렉션된 표준 핸들이 생성할 수 있습니다. 이 기능을 사용하면 상위 프로세스에서를 입력 및 출력 자식 프로세스의 받을 수 있습니다.

참고 일부 콘솔 기반 응용 프로그램은 표준 핸들 입/출력 (IO) 연산에 사용하지 마십시오. Win32 API 이러한 프로세스 리디렉션을 지원하지 않습니다.
추가 정보
CreateProcess() API를 STARTUPINFO 구조를 통해 자식 기반으로 콘솔 프로세스의 표준 핸들 리디렉션할 수 있습니다. dwFlags 멤버 STARTF_USESTDHANDLES로 설정한 다음 표준 핸들 자식 콘솔 기반 프로세스 중 다음 STARTUPINFO 구성원을 지정할 경우:
   HANDLE hStdInput - Standard input handle of the child process.   HANDLE hStdOutput - Standard output handle of the child process.   HANDLE hStdError - Standard error handle of the child process.				
두 파이프 핸들을, 파일 핸들, 이러한 핸들을 설정할 수 또는 동기 할 수 있는 핸들 읽고 ReadFile() 및 WriteFile() API를 통해 씁니다. 핸들을 상속할 수 있어야 하며 CreateProcess() API 상속 가능한 핸들의 TRUE bInheritHandles 매개 변수를 지정하여 자식 프로세스에서 상속할 수 있는지 지정해야 합니다. 부모 프로세스 경우에만 하나 또는 두 개의 표준 핸들을 리디렉션하는 경우 GetStdHandle()에 대한 특정 핸들을 지정하면 없이 리디렉션 평소와 같이 표준 핸들을 만들지 자식을 발생합니다. 부모 프로세스가 표준 출력 및 오류 자식 프로세스의 리디렉션 하는 경우, 예를 들어, 다음 STARTUPINFO 구조체의 hStdInput 멤버를 같이 채워진:
   hStdInput = GetStdHandle(STD_INPUT_HANDLE);				
printf() 및 fprintf() 같은 C 런타임 함수를 사용하는 노트 자식 프로세스가 리디렉션된 때 제대로 작동할 수 있습니다. C 런타임 함수를 별도의 IO 버퍼를 유지 관리합니다. 즉시 각 IO 호출한 후 리디렉션될 때 이러한 버퍼는 플러시할 수 수 없습니다. 따라서 printf() 호출 또는 입력 리디렉션 파이프 출력 getch() 호출에서 즉시 플러시되지 및 지연, 때로는 무제한으로 지연이 발생합니다. 자식 프로세스 C 런타임 IO 함수 호출할 때마다 후 IO 버퍼를 플러시합니다 경우 이 문제가 발생하지 않습니다. 자식 프로세스 C 런타임 IO 버퍼를 플러시할 수 있습니다. 프로세스가 fflush() 함수를 호출하여 해당 C 런타임 IO 버퍼를 플러시할 수 있습니다.

참고 특정 자식 프로세스가 표준 핸들 리디렉션할 때 Windows 95 및 Windows 98 단계가 필요합니다.

다음 샘플에서는 표준 입력, 출력 및 오류 CreateProcess 호출에 지정된 자식 프로세스의 리디렉션합니다. 이 샘플에서는 제공된 콘솔 프로세스를 (Child.c) 리디렉션합니다.

예제 코드

   /*++      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>   #pragma comment(lib, "User32.lib")   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,"Child.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());   }   //////////////////////////////////////////////////////////////////////    // child.c   // Echoes all input to stdout. This will be redirected by the redirect   // sample. Compile and build child.c as a Win32 Console application and   // put it in the same directory as the redirect sample.   //    #include<windows.h>   #include<stdio.h>   #include<string.h>   void main ()   {      FILE*    fp;      CHAR     szInput[1024];      // Open the console. By doing this, you can send output directly to      // the console that will not be redirected.      fp = fopen("CON", "w");      if (!fp) {         printf("Error opening child console - perhaps there is none.\n");         fflush(NULL);      }      else      {      // Write a message direct to the console (will not be redirected).         fprintf(fp,"This data is being printed directly to the\n");         fprintf(fp,"console and will not be redirected.\n\n");         fprintf(fp,"Since the standard input and output have been\n");         fprintf(fp,"redirected data sent to and from those handles\n");         fprintf(fp,"will be redirected.\n\n");         fprintf(fp,"To send data to the std input of this process.\n");         fprintf(fp,"Click on the console window of the parent process\n");         fprintf(fp,"(redirect), and enter data from it's console\n\n");         fprintf(fp,"To exit this process send the string 'exit' to\n");         fprintf(fp,"it's standard input\n");         fflush(fp);      }      ZeroMemory(szInput,1024);      while (TRUE)      {         gets(szInput);         printf("Child echoing [%s]\n",szInput);         fflush(NULL);  // Must flush output buffers or else redirection                        // will be problematic.         if (!_stricmp(szInput,"Exit") )            break;         ZeroMemory(szInput,strlen(szInput) );      }   }
참조
MSDN 라이브러리 SDK 설명서를: CreateProcess(), STARTUPINFO 구조

Win32 플랫폼 SDK에서 샘플 상속:
   \MSSDK\samples\winbase\ipc\inherit				
상속 리디렉션할 리디렉션 stdhandles

Warning: This article has been translated automatically

속성

문서 ID: 190351 - 마지막 검토: 11/21/2006 15:28:50 - 수정: 7.1

  • Microsoft Win32 Application Programming Interface
  • kbmt kbapi kbconsole kbfaq kbhowto kbipc kbkernbase KB190351 KbMtko
피드백
if?DI=4050&did=1&t=">icrosoft.com/c.gif?DI=4050&did=1&t=">0&did=1&t=">ipt"> Asimov.clickstreamTracker.init(); > + (window.location.protocol) + "//c.microsoft.com/ms.js'><\/script>"); &t=">