Πώς να παραγάγει διεργασίες κονσόλας με λαβές ανακατεύθυνσης βασική

Μεταφράσεις άρθρων Μεταφράσεις άρθρων
Αναγν. άρθρου: 190351 - Δείτε τα προϊόντα στα οποία αναφέρεται το συγκεκριμένο άρθρο.
Ανάπτυξη όλων | Σύμπτυξη όλων

Σε αυτήν τη σελίδα

Περίληψη

Αυτό το άρθρο περιγράφει τον τρόπο για να γίνει ανακατεύθυνση της εισόδου και εξόδου από μια εξαρτημένη διεργασία που λαμβάνει δεδομένα εισόδου από το δείκτη χειρισμού τυπικής εισόδου ή αποστέλλει την έξοδο στο δείκτη χειρισμού καθιερωμένο όγκο παραγωγής. Το API του Win32 επιτρέπει σε εφαρμογές να παραγάγει μια εξαρτημένη διεργασία κονσόλας με ανακατευθυνόμενη τυπικό λαβές. Αυτή η δυνατότητα επιτρέπει σε μια διεργασία γονικό για αποστολή και λήψη της εισόδου και εξόδου της διεργασίας παιδιού.

ΣΗΜΕΙΩΣΗΟρισμένες εφαρμογές κονσόλας με βάση δεν χρησιμοποιούν την τυπική δείκτες χειρισμού για τις λειτουργίες εισόδου/εξόδου (IO). Το API του Win32 δεν υποστηρίζει την ανακατεύθυνση από αυτές τις διαδικασίες.

Περισσότερες πληροφορίες

Το API CreateProcess() μέσω της δομής 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. Πρέπει να είναι μεταβιβάσιμη τους δείκτες χειρισμού και το API CreateProcess() πρέπει να καθορίσετε ότι λαβές μεταβίβασης μεταβιβάζονται η εξαρτημένη διεργασία καθορίζοντας TRUE στην παράμετρο bInheritHandles. Εάν η γονική διεργασία θέλει μόνο να ανακατευθύνετε μία ή δύο τυπικές λαβές, καθορίζοντας GetStdHandle() για τις συγκεκριμένες λαβές προκαλεί το παιδί να δημιουργήσει ο δείκτης χειρισμού τυπικής όπως κάνατε κανονικά χωρίς ανακατεύθυνσης. Για παράδειγμα, αν η γονική διεργασία πρέπει μόνο να ανακατευθύνει την τυπική έξοδο και το σφάλμα της διαδικασίας παιδί, τότε το μέλος hStdInput της δομής STARTUPINFO συμπληρώνεται ως εξής:
   hStdInput = GetStdHandle(STD_INPUT_HANDLE);
				
ΣΗΜΕΙΩΣΗΠαιδί διεργασίες που χρησιμοποιούν τέτοιες συναρτήσεις χρόνου εκτέλεσης C ως printf() και fprintf() να συμπεριφέρονται καλά όταν γίνει ανακατεύθυνση. Οι συναρτήσεις χρόνου εκτέλεσης C διατηρούν ξεχωριστές των buffer εισόδου/ΕΞΌΔΟΥ. Κατά την ανακατεύθυνση, αυτών των buffers μπορεί να μην η Εκκαθάριση αμέσως μετά την κλήση κάθε εισόδου/ΕΞΌΔΟΥ. Ως αποτέλεσμα, η έξοδος στη διοχέτευση ανακατεύθυνση μιας κλήσης printf() ή τα δεδομένα εισόδου από μια κλήση getch() δεν εκκαθάριση αμέσως και καθυστερήσεις, μερικές φορές άπειρο καθυστερήσεις προκύψει. Αυτό το ζήτημα είναι αποφεύγονται εάν η εξαρτημένη διεργασία πραγματοποιεί εκκαθάριση των buffer εισόδου/ΕΞΌΔΟΥ μετά από κάθε κλήση σε μια λειτουργία εισόδου/ΕΞΌΔΟΥ κατά την εκτέλεση του C. Η εξαρτημένη διεργασία να εκκένωση της C των buffer εισόδου/ΕΞΌΔΟΥ κατά το χρόνο εκτέλεσης. Μια διαδικασία να εκκένωση της C των buffer εισόδου/ΕΞΌΔΟΥ κατά το χρόνο εκτέλεσης από την κλήση της συνάρτησης fflush().

ΣΗΜΕΙΩΣΗΤα 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) );

      }
   }

Αναφορές

Τεκμηρίωση SDK βιβλιοθήκη MSDN: CreateProcess(); STARTUPINFO δομή

Η μεταβίβαση δείγματος στο SDK της πλατφόρμας Win32 στην περιοχή:
   \MSSDK\samples\winbase\ipc\inherit
				

Ιδιότητες

Αναγν. άρθρου: 190351 - Τελευταία αναθεώρηση: Σάββατο, 18 Δεκεμβρίου 2010 - Αναθεώρηση: 2.0
Οι πληροφορίες σε αυτό το άρθρο ισχύουν για:
  • Microsoft Win32 Application Programming Interface
Λέξεις-κλειδιά: 
kbapi kbconsole kbFAQ kbhowto kbipc kbkernbase kbmt KB190351 KbMtel
Μηχανικά μεταφρασμένο
ΣΗΜΑΝΤΙΚΟ: Αυτό το άρθρο είναι προϊόν λογισμικού μηχανικής μετάφρασης της Microsoft και όχι ανθρώπινης μετάφρασης. Η Microsoft σάς προσφέρει άρθρα που είναι προϊόντα ανθρώπινης αλλά και μηχανικής μετάφρασης έτσι ώστε να έχετε πρόσβαση σε όλα τα άρθρα της Γνωσιακής Βάσης μας στη δική σας γλώσσα. Ωστόσο, ένα άρθρο που έχει προκύψει από μηχανική μετάφραση δεν είναι πάντα άριστης ποιότητας. Ενδέχεται να περιέχει λεξιλογικά, συντακτικά ή γραμματικά λάθη, όπως ακριβώς τα λάθη που θα έκανε ένας μη φυσικός ομιλητής επιχειρώντας να μιλήσει τη γλώσσα σας. Η Microsoft δεν φέρει καμία ευθύνη για τυχόν ανακρίβειες, σφάλματα ή ζημίες που προκύψουν λόγω τυχόν παρερμηνειών στη μετάφραση του περιεχομένου ή χρήσης του από τους πελάτες της. Επίσης, η Microsoft πραγματοποιεί συχνά ενημερώσεις στο λογισμικό μηχανικής μετάφρασης.
Η αγγλική έκδοση αυτού του άρθρου είναι η ακόλουθη:190351

Αποστολή σχολίων

 

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