Bạn hiện đang ngoại tuyến, hãy chờ internet để kết nối lại

Làm thế nào để đẻ trứng quá trình giao diện điều khiển với chuyển hướng xử lý tiêu chuẩn

QUAN TRỌNG: Bài viết này được dịch bằng phần mềm dịch máy của Microsoft chứ không phải do con người dịch. Microsoft cung cấp các bài viết do con người dịch và cả các bài viết do máy dịch để bạn có thể truy cập vào tất cả các bài viết trong Cơ sở Kiến thức của chúng tôi bằng ngôn ngữ của bạn. Tuy nhiên, bài viết do máy dịch không phải lúc nào cũng hoàn hảo. Loại bài viết này có thể chứa các sai sót về từ vựng, cú pháp hoặc ngữ pháp, giống như một người nước ngoài có thể mắc sai sót khi nói ngôn ngữ của bạn. Microsoft không chịu trách nhiệm về bất kỳ sự thiếu chính xác, sai sót hoặc thiệt hại nào do việc dịch sai nội dung hoặc do hoạt động sử dụng của khách hàng gây ra. Microsoft cũng thường xuyên cập nhật phần mềm dịch máy này.

Nhấp chuột vào đây để xem bản tiếng Anh của bài viết này:190351
TÓM TẮT
Bài viết này mô tả cách để chuyển hướng các đầu vào và đầu ra của một quá trình con mà nhận được đầu vào từ các xử lý đầu vào tiêu chuẩn hoặc gửi ra để xử lý đầu ra tiêu chuẩn. Win32 API cho phép các ứng dụng để đẻ trứng một đứa trẻ bàn giao tiếp với quá trình chuyển chốt tiêu chuẩn. Tính năng này cho phép một quá trình phụ huynh để gửi và nhận các đầu vào và đầu ra của quá trình con.

Chú ý Một số ứng dụng dựa trên giao diện điều khiển không sử dụng xử lý tiêu chuẩn cho đầu vào/đầu ra (IO) hoạt động của họ. Win32 API hỗ trợ chuyển hướng các quá trình.
THÔNG TIN THÊM
CreateProcess() thông qua cấu trúc STARTUPINFO API cho phép bạn đểchuyển hướng các chốt tiêu chuẩn của một quá trình giao diện điều khiển dựa trên con. Nếu tài khoản của dwFlags được thiết lập để STARTF_USESTDHANDLES, sau đó thành viên STARTUPINFO sau đây chỉ ra các chốt tiêu chuẩn của quá trình giao diện điều khiển dựa trên con:
   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.				
Bạn có thể thiết lập các chốt cho một trong hai một ống xử lý, xử lý tập tin, hoặc bất kỳxử lý mà có thể làm đồng bộ lần đọc và viết thông qua readfile () vàWriteFile() API. Các chốt phải được thừa kế và CreateProcess()API phải chỉ ra rằng có thể thừa kế xử lý đang được thừa kế bởi conxử lý bằng cách xác định đúng trong tham số bInheritHandles. Nếu phụ huynhquá trình chỉ muốn chuyển hướng một hoặc hai tiêu chuẩn chốt, chỉ địnhGetStdHandle() cho xử lý cụ thể gây ra các con để tạo ra cáctiêu chuẩn xử lý vì nó thường sẽ không chuyển hướng. Ví dụ, nếuquá trình phụ huynh chỉ cần để chuyển hướng đầu ra tiêu chuẩn và lỗi củaquá trình trẻ em, sau đó các thành viên hStdInput của cấu trúc STARTUPINFO được làm đầy như sau:
   hStdInput = GetStdHandle(STD_INPUT_HANDLE);				
Chú ý Các quá trình con quý vị sử dụng các chức năng thời gian chạy c như printf() và fprintf() có thể hành xử kém khi đổi hướng. Các chức năng thời gian chạy cduy trì riêng biệt IO bộ đệm. Khi chuyển hướng, các bộ đệm có thể khôngđỏ ửng ngay lập tức sau mỗi cuộc gọi IO. Kết quả là, đầu ra cho cácđường ống chuyển hướng cuộc gọi printf() hoặc đầu vào từ một cuộc gọi getch() không phải làđỏ ửng ngay lập tức và chậm trễ, trì hoãn vô hạn đôi khi xảy ra. Vấn đề này tránh nếu trình con flushes bộ đệm IO sau mỗi cuộc gọi đến một chức năng IO lần chạy C. Chỉ là quá trình trẻ em có thể tuôn ra của nó thời gian chạy C IO bộ đệm. Một quá trình có thể tuôn ra của nó thời gian chạy C IO bộ đệm bằng cách gọi các chức năng fflush().

Chú ý Windows 95 và Windows 98 đòi hỏi một bước thêm khi bạn chuyển hướng các chốt tiêu chuẩn của một số các quá trình con.

Mẫu sau chuyển hướng tiêu chuẩn đầu vào, đầu ra và lỗi của cácquá trình trẻ em được chỉ rõ trong các cuộc gọi CreateProcess. Mẫu này chuyển hướnggiao diện điều khiển được cung cấp trình (Child.c).

Mã mẫu

   /*++      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) );      }   }
THAM KHẢO
MSDN Library SDK tài liệu: CreateProcess(); Cấu trúc STARTUPINFO

Thừa kế mẫu trong SDK Win32 nền tảng dưới:
   \MSSDK\samples\winbase\ipc\inherit				
Thừa kế việc chuyển hướng đổi hướng stdhandles

Cảnh báo: Bài viết này được dịch tự động

Thuộc tính

ID Bài viết: 190351 - Xem lại Lần cuối: 08/20/2011 10:21:00 - Bản sửa đổi: 2.0

Microsoft Win32 Application Programming Interface

  • kbapi kbconsole kbFAQ kbhowto kbipc kbkernbase kbmt KB190351 KbMtvi
Phản hồi