Bagaimana untuk bertelur konsol proses dengan standar diarahkan menangani

Terjemahan Artikel Terjemahan Artikel
ID Artikel: 190351 - Melihat produk di mana artikel ini berlaku.
Perbesar semua | Perkecil semua

Pada Halaman ini

RINGKASAN

Artikel ini menjelaskan cara untuk mengarahkan input dan output dari proses anak yang menerima masukan dari standar menangani masukan atau mengirim output untuk menangani output standar. Win32 API memungkinkan aplikasi untuk bertelur proses konsol anak dengan menangani standar diarahkan. Fitur ini memungkinkan proses induk untuk mengirim dan menerima masukan dan keluaran dari proses anak.

Catatan Beberapa aplikasi konsol berbasis tidak menggunakan pegangan standar untuk mereka input/output (IO) operasi. Win32 API tidak mendukung pengalihan dari proses ini.

INFORMASI LEBIH LANJUT

CreateProcess() API melalui struktur STARTUPINFO memungkinkan Anda untuk mengarahkan menangani standar proses konsol berbasis anak. Jika anggota dwFlags diatur ke STARTF_USESTDHANDLES, kemudian STARTUPINFO anggota berikut menentukan menangani standar proses konsol berbasis anak:
   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.
				
Anda dapat menangani ini baik menangani pipa, menangani file, atau apapun pegangan yang dapat melakukan sinkron membaca dan menulis melalui readfile () dan WriteFile() API. Pegangan harus diwariskan dan CreateProcess() API harus menentukan diwariskan pegangan yang akan diwariskan oleh anak proses dengan menentukan benar dalam bInheritHandles parameter. Jika orang tua proses hanya keinginan untuk mengarahkan satu atau dua standar menangani, menentukan GetStdHandle() untuk menangani tertentu menyebabkan anak untuk membuat standar menangani seperti biasanya akan tanpa pengalihan. Sebagai contoh, jika proses induk hanya perlu mengarahkan output standar dan kesalahan proses anak, maka anggota hStdInput STARTUPINFO struktur penuh sebagai berikut:
   hStdInput = GetStdHandle(STD_INPUT_HANDLE);
				
Catatan Anak proses yang menggunakan fungsi run-time seperti c sebagai printf() dan fprintf() dapat berperilaku buruk ketika dialihkan. Fungsi run-time c mempertahankan terpisah IO buffer. Ketika dialihkan, buffer ini tidak mungkin memerah segera setelah masing-masing panggilan IO. Sebagai hasilnya, keluaran pipa pengalihan panggilan printf() atau masukan dari panggilan getch() bukanlah memerah segera dan penundaan, kadang-kadang-tak terbatas penundaan terjadi. Masalah ini adalah dihindari jika proses anak flushes buffer IO setelah masing-masing panggilan ke fungsi IO run-time C. Hanya proses anak dapat membersihkan yang c run-time IO buffer. Proses dapat membersihkan buffer IO run-time dengan c dengan memanggil fungsi fflush().

Catatan Windows 95 dan Windows 98 membutuhkan langkah tambahan ketika Anda mengarahkan menangani standar proses anak tertentu.

Berikut contoh pengalihan standar input, output, dan kesalahan proses anak yang ditentukan dalam panggilan CreateProcess. Sampel ini pengalihan proses disediakan konsol (Child.c).

Kode sampel

   /*++

      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) );

      }
   }

REFERENSI

MSDN perpustakaan SDK dokumentasi: CreateProcess(); Struktur STARTUPINFO

Mewarisi sampel di Win32 Platform SDK di bawah:
   \MSSDK\samples\winbase\ipc\inherit
				

Properti

ID Artikel: 190351 - Kajian Terakhir: 19 September 2011 - Revisi: 2.0
Berlaku bagi:
  • Microsoft Win32 Application Programming Interface
Kata kunci: 
kbapi kbconsole kbFAQ kbhowto kbipc kbkernbase kbmt KB190351 KbMtid
Penerjemahan Mesin
PENTING: Artikel ini diterjemahkan menggunakan perangkat lunak mesin penerjemah Microsoft dan bukan oleh seorang penerjemah. Microsoft menawarkan artikel yang diterjemahkan oleh seorang penerjemah maupun artikel yang diterjemahkan menggunakan mesin sehingga Anda akan memiliki akses ke seluruh artikel baru yang diterbitkan di Pangkalan Pengetahuan (Knowledge Base) dalam bahasa yang Anda gunakan. Namun, artikel yang diterjemahkan menggunakan mesin tidak selalu sempurna. Artikel tersebut mungkin memiliki kesalahan kosa kata, sintaksis, atau tata bahasa, hampir sama seperti orang asing yang berbicara dalam bahasa Anda. Microsoft tidak bertanggung jawab terhadap akurasi, kesalahan atau kerusakan yang disebabkan karena kesalahan penerjemahan konten atau penggunaannya oleh para pelanggan. Microsoft juga sering memperbarui perangkat lunak mesin penerjemah.
Klik disini untuk melihat versi Inggris dari artikel ini:190351

Berikan Masukan

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com