Process.CancelOutputRead Метод

Определение

Отменяет операцию асинхронного чтения в перенаправленном потоке StandardOutput приложения.

public:
 void CancelOutputRead();
public void CancelOutputRead ();
[System.Runtime.InteropServices.ComVisible(false)]
public void CancelOutputRead ();
member this.CancelOutputRead : unit -> unit
[<System.Runtime.InteropServices.ComVisible(false)>]
member this.CancelOutputRead : unit -> unit
Public Sub CancelOutputRead ()
Атрибуты

Исключения

Поток StandardOutput не включен для асинхронных операций чтения.

Примеры

В следующем примере запускается nmake команда с предоставленными пользователем аргументами. Потоки ошибок и выходных данных считываются асинхронно; Собранные текстовые строки отображаются в консоли, а также записываются в файл журнала. Если выходные данные команды превышают указанное количество строк, асинхронные операции чтения отменяются.

ref class ProcessNMakeStreamRedirection
{
private:
   // Define static variables shared by class methods.
   static StreamWriter^ buildLogStream = nullptr;
   static Mutex^ logMutex = gcnew Mutex;
   static int maxLogLines = 25;
   static int currentLogLines = 0;

public:
   static void RedirectNMakeCommandStreams()
   {
      String^ nmakeArguments = nullptr;
      Process^ nmakeProcess;
      
      // Get the input nmake command-line arguments.
      Console::WriteLine( "Enter the NMake command line arguments (@commandfile or /f makefile, etc):" );
      String^ inputText = Console::ReadLine();
      if (  !String::IsNullOrEmpty( inputText ) )
      {
         nmakeArguments = inputText;
      }

      Console::WriteLine( "Enter max line limit for log file (default is 25):" );
      inputText = Console::ReadLine();
      if (  !String::IsNullOrEmpty( inputText ) )
      {
         if (  !Int32::TryParse( inputText, maxLogLines ) )
         {
            maxLogLines = 25;
         }
      }
      Console::WriteLine( "Output beyond {0} lines will be ignored.",
         maxLogLines.ToString() );
      
      // Initialize the process and its StartInfo properties.
      nmakeProcess = gcnew Process;
      nmakeProcess->StartInfo->FileName = "NMake.exe";
      
      // Build the nmake command argument list.
      if (  !String::IsNullOrEmpty( nmakeArguments ) )
      {
         nmakeProcess->StartInfo->Arguments = nmakeArguments;
      }
      
      // Set UseShellExecute to false for redirection.
      nmakeProcess->StartInfo->UseShellExecute = false;
      
      // Redirect the standard output of the nmake command.  
      // Read the stream asynchronously using an event handler.
      nmakeProcess->StartInfo->RedirectStandardOutput = true;
      nmakeProcess->OutputDataReceived += gcnew DataReceivedEventHandler( NMakeOutputDataHandler );
      
      // Redirect the error output of the nmake command. 
      nmakeProcess->StartInfo->RedirectStandardError = true;
      nmakeProcess->ErrorDataReceived += gcnew DataReceivedEventHandler( NMakeErrorDataHandler );

      logMutex->WaitOne();

      currentLogLines = 0;
      
      // Write a header to the log file.
      String^ buildLogFile = "NmakeCmd.Txt";
      try
      {
         buildLogStream = gcnew StreamWriter( buildLogFile,true );
      }
      catch ( Exception^ e ) 
      {
         Console::WriteLine( "Could not open output file {0}", buildLogFile );
         Console::WriteLine( "Exception = {0}", e->ToString() );
         Console::WriteLine( e->Message->ToString() );

         buildLogStream = nullptr;
      }

      if ( buildLogStream != nullptr )
      {
         Console::WriteLine( "Nmake output logged to {0}", buildLogFile );

         buildLogStream->WriteLine();
         buildLogStream->WriteLine( DateTime::Now.ToString() );
         if (  !String::IsNullOrEmpty( nmakeArguments ) )
         {
            buildLogStream->Write( "Command line = NMake {0}", nmakeArguments );
         }
         else
         {
            buildLogStream->Write( "Command line = Nmake" );
         }
         buildLogStream->WriteLine();
         buildLogStream->Flush();

         logMutex->ReleaseMutex();
         
         // Start the process.
         Console::WriteLine();
         Console::WriteLine( "\nStarting Nmake command" );
         Console::WriteLine();
         nmakeProcess->Start();
         
         // Start the asynchronous read of the output stream.
         nmakeProcess->BeginOutputReadLine();
         
         // Start the asynchronous read of the error stream.
         nmakeProcess->BeginErrorReadLine();
         
         // Let the nmake command run, collecting the output.
         nmakeProcess->WaitForExit();

         nmakeProcess->Close();
         buildLogStream->Close();
         logMutex->Dispose();
      }
   }

private:
   static void NMakeOutputDataHandler( Object^ sendingProcess,
      DataReceivedEventArgs^ outLine )
   {
      // Collect the output, displaying it to the screen and 
      // logging it to the output file.  Cancel the read
      // operation when the maximum line limit is reached.

      if (  !String::IsNullOrEmpty( outLine->Data ) )
      {
         logMutex->WaitOne();

         currentLogLines++;
         if ( currentLogLines > maxLogLines )
         {
            // Display the line to the console.
            // Skip writing the line to the log file.
            Console::WriteLine( "StdOut: {0}", outLine->Data->ToString() );
         }
         else
         if ( currentLogLines == maxLogLines )
         {
            LogToFile( "StdOut", "<Max build log limit reached!>", true );
            
            // Stop reading the output streams.
            Process^ p = dynamic_cast<Process^>(sendingProcess);
            if ( p != nullptr )
            {
               p->CancelOutputRead();
               p->CancelErrorRead();
            }
         }
         else
         {
            // Write the line to the log file.
            LogToFile( "StdOut", outLine->Data, true );
         }
         logMutex->ReleaseMutex();
      }
   }

   static void NMakeErrorDataHandler( Object^ sendingProcess,
      DataReceivedEventArgs^ errLine )
   {
      
      // Collect the error output, displaying it to the screen and 
      // logging it to the output file.  Cancel the error output
      // read operation when the maximum line limit is reached.

      if (  !String::IsNullOrEmpty( errLine->Data ) )
      {
         logMutex->WaitOne();

         currentLogLines++;
         if ( currentLogLines > maxLogLines )
         {
            
            // Display the line to the console.
            // Skip writing the line to the log file.
            Console::WriteLine( "StdErr: {0}", errLine->Data->ToString() );
         }
         else
         if ( currentLogLines == maxLogLines )
         {
            LogToFile( "StdOut", "<Max build log limit reached!>", true );
            
            // Stop reading the output streams.
            Process^ p = dynamic_cast<Process^>(sendingProcess);
            if ( p != nullptr )
            {
               p->CancelOutputRead();
               p->CancelErrorRead();
            }
         }
         else
         {
            // Write the line to the log file.
            LogToFile( "StdErr", errLine->Data, true );
         }
         logMutex->ReleaseMutex();
      }
   }

   static void LogToFile( String^ logPrefix, String^ logText,
      bool echoToConsole )
   {
      // Write the specified line to the log file stream.
      StringBuilder^ logString = gcnew StringBuilder;

      if (  !String::IsNullOrEmpty( logPrefix ) )
      {
         logString->AppendFormat( "{0}> ", logPrefix );
      }

      if (  !String::IsNullOrEmpty( logText ) )
      {
         logString->Append( logText );
      }

      if ( buildLogStream != nullptr )
      {
         buildLogStream->WriteLine(  "[{0}] {1}",
            DateTime::Now.ToString(), logString->ToString() );
         buildLogStream->Flush();
      }

      if ( echoToConsole )
      {
         Console::WriteLine( logString->ToString() );
      }
   }
};
namespace ProcessAsyncStreamSamples
{
    class ProcessNMakeStreamRedirection
    {
        // Define static variables shared by class methods.
        private static StreamWriter buildLogStream =null;
        private static Mutex logMutex = new Mutex();
        private static int maxLogLines = 25;
        private static int currentLogLines = 0;

        public static void RedirectNMakeCommandStreams()
        {
            String nmakeArguments = null;
            Process nmakeProcess;

            // Get the input nmake command-line arguments.
            Console.WriteLine("Enter the NMake command line arguments " +
                "(@commandfile or /f makefile, etc):");
            String inputText = Console.ReadLine();
            if (!String.IsNullOrEmpty(inputText))
            {
                nmakeArguments = inputText;
            }

            Console.WriteLine("Enter max line limit for log file (default is 25):");
            inputText = Console.ReadLine();
            if (!String.IsNullOrEmpty(inputText))
            {
                if (!Int32.TryParse(inputText, out maxLogLines))
                {
                    maxLogLines = 25;
                }
            }
            Console.WriteLine("Output beyond {0} lines will be ignored.",
                maxLogLines);

            // Initialize the process and its StartInfo properties.
            nmakeProcess = new Process();
            nmakeProcess.StartInfo.FileName = "NMake.exe";

            // Build the nmake command argument list.
            if (!String.IsNullOrEmpty(nmakeArguments))
            {
                nmakeProcess.StartInfo.Arguments = nmakeArguments;
            }

            // Set UseShellExecute to false for redirection.
            nmakeProcess.StartInfo.UseShellExecute = false;

            // Redirect the standard output of the nmake command.
            // Read the stream asynchronously using an event handler.
            nmakeProcess.StartInfo.RedirectStandardOutput = true;
            nmakeProcess.OutputDataReceived += new DataReceivedEventHandler(NMakeOutputDataHandler);

            // Redirect the error output of the nmake command.
            nmakeProcess.StartInfo.RedirectStandardError = true;
            nmakeProcess.ErrorDataReceived += new DataReceivedEventHandler(NMakeErrorDataHandler);

            logMutex.WaitOne();

            currentLogLines = 0;

            // Write a header to the log file.
            const String buildLogFile = "NmakeCmd.Txt";
            try
            {
                buildLogStream = new StreamWriter(buildLogFile, true);
            }
            catch (Exception e)
            {
                Console.WriteLine("Could not open output file {0}", buildLogFile);
                Console.WriteLine("Exception = {0}", e.ToString());
                Console.WriteLine(e.Message);

                buildLogStream = null;
            }

            if (buildLogStream != null)
            {
                Console.WriteLine("Nmake output logged to {0}",
                    buildLogFile);

                buildLogStream.WriteLine();
                buildLogStream.WriteLine(DateTime.Now.ToString());
                if (!String.IsNullOrEmpty(nmakeArguments))
                {
                    buildLogStream.Write("Command line = NMake {0}",
                        nmakeArguments);
                }
                else
                {
                    buildLogStream.Write("Command line = Nmake");
                }
                buildLogStream.WriteLine();
                buildLogStream.Flush();

                logMutex.ReleaseMutex();

                // Start the process.
                Console.WriteLine();
                Console.WriteLine("\nStarting Nmake command...");
                Console.WriteLine();
                nmakeProcess.Start();

                // Start the asynchronous read of the error stream.
                nmakeProcess.BeginErrorReadLine();

                // Start the asynchronous read of the output stream.
                nmakeProcess.BeginOutputReadLine();

                // Let the nmake command run, collecting the output.
                nmakeProcess.WaitForExit();

                nmakeProcess.Close();
                buildLogStream.Close();
                logMutex.Dispose();
            }
        }

        private static void NMakeOutputDataHandler(object sendingProcess,
            DataReceivedEventArgs outLine)
        {
            // Collect the output, displaying it to the screen and
            // logging it to the output file.  Cancel the read
            // operation when the maximum line limit is reached.

            if (!String.IsNullOrEmpty(outLine.Data))
            {
                logMutex.WaitOne();

                currentLogLines++;
                if (currentLogLines > maxLogLines)
                {
                    // Display the line to the console.
                    // Skip writing the line to the log file.
                    Console.WriteLine("StdOut: {0}", outLine.Data);
                }
                else if (currentLogLines == maxLogLines)
                {
                    LogToFile("StdOut", "<Max build log limit reached!>",
                        true);

                    // Stop reading the output streams.
                    Process p = sendingProcess as Process;
                    if (p != null)
                    {
                        p.CancelOutputRead();
                        p.CancelErrorRead();
                    }
                }
                else
                {
                    // Write the line to the log file.
                    LogToFile("StdOut", outLine.Data, true);
                }
                logMutex.ReleaseMutex();
            }
        }

        private static void NMakeErrorDataHandler(object sendingProcess,
            DataReceivedEventArgs errLine)
        {
            // Collect error output, displaying it to the screen and
            // logging it to the output file.  Cancel the error output
            // read operation when the maximum line limit is reached.

            if (!String.IsNullOrEmpty(errLine.Data))
            {
                logMutex.WaitOne();

                currentLogLines++;
                if (currentLogLines > maxLogLines)
                {
                    // Display the error line to the console.
                    // Skip writing the line to the log file.
                    Console.WriteLine("StdErr: {0}", errLine.Data);
                }
                else if (currentLogLines == maxLogLines)
                {
                    LogToFile("StdErr", "<Max build log limit reached!>",
                        true);

                    // Stop reading the output streams
                    Process p = sendingProcess as Process;
                    if (p != null)
                    {
                        p.CancelErrorRead();
                        p.CancelOutputRead();
                    }
                }
                else
                {
                    // Write the line to the log file.
                    LogToFile("StdErr", errLine.Data, true);
                }

                logMutex.ReleaseMutex();
            }
        }

        private static void LogToFile(String logPrefix,
            String logText, bool echoToConsole)
        {
            // Write the specified line to the log file stream.
            StringBuilder logString = new StringBuilder();

            if (!String.IsNullOrEmpty(logPrefix))
            {
                logString.AppendFormat("{0}> ", logPrefix);
            }

            if (!String.IsNullOrEmpty(logText))
            {
                logString.Append(logText);
            }

            if (buildLogStream != null)
            {
                buildLogStream.WriteLine("[{0}] {1}",
                    DateTime.Now.ToString(), logString.ToString());
                buildLogStream.Flush();
            }

            if (echoToConsole)
            {
                Console.WriteLine(logString.ToString());
            }
        }
    }
}
' Define the namespaces used by this sample.
Imports System.Text
Imports System.IO
Imports System.Diagnostics
Imports System.Threading
Imports System.ComponentModel

Class ProcessNMakeStreamRedirection

   ' Define static variables shared by class methods.
   Private Shared buildLogStream As StreamWriter = Nothing
   Private Shared logMutex As Mutex = New Mutex()
   Private Shared maxLogLines As Integer = 25
   Private Shared currentLogLines As Integer = 0
   
   
   Public Shared Sub RedirectNMakeCommandStreams()
      Dim nmakeArguments As String = Nothing
      Dim nmakeProcess As Process
      
      ' Get the input nmake command-line arguments.
      Console.WriteLine("Enter the NMake command line arguments" + _
          " (@commandfile or /f makefile, etc):")
      Dim inputText As String = Console.ReadLine()
      If Not String.IsNullOrEmpty(inputText) Then
         nmakeArguments = inputText
      End If
      
      Console.WriteLine("Enter max line limit for log file (default is 25):")
      inputText = Console.ReadLine()
      If Not String.IsNullOrEmpty(inputText) Then
         If Not Int32.TryParse(inputText, maxLogLines) Then
            maxLogLines = 25
         End If
      End If
      Console.WriteLine("Output beyond {0} lines will be ignored.", _
          maxLogLines)
      
      ' Initialize the process and its StartInfo properties.
      nmakeProcess = New Process()
      nmakeProcess.StartInfo.FileName = "NMake.exe"
      
      ' Build the nmake command argument list.
      If Not String.IsNullOrEmpty(nmakeArguments) Then
         nmakeProcess.StartInfo.Arguments = nmakeArguments
      End If
      
      ' Set UseShellExecute to false for redirection.
      nmakeProcess.StartInfo.UseShellExecute = False
      
      ' Redirect the standard output of the nmake command.  
      ' Read the stream asynchronously using an event handler.
      nmakeProcess.StartInfo.RedirectStandardOutput = True
      AddHandler nmakeProcess.OutputDataReceived, _
                AddressOf NMakeOutputDataHandler
      
      ' Redirect the error output of the nmake command. 
      nmakeProcess.StartInfo.RedirectStandardError = True
      AddHandler nmakeProcess.ErrorDataReceived, _
                AddressOf NMakeErrorDataHandler

      logMutex.WaitOne()

      currentLogLines = 0
    
      ' Write a header to the log file.
      Const buildLogFile As String = "NmakeCmd.Txt"
      Try 
          buildLogStream = new StreamWriter(buildLogFile, true)
      Catch e As Exception
          Console.WriteLine("Could not open output file {0}", buildLogFile)
          Console.WriteLine("Exception = {0}", e.ToString())
          Console.WriteLine(e.Message)

          buildLogStream = Nothing
      End Try

      If Not buildLogStream Is Nothing Then
               
          Console.WriteLine("Nmake output logged to {0}", _
              buildLogFile)
    
          buildLogStream.WriteLine()
          buildLogStream.WriteLine(DateTime.Now.ToString())
          
          If Not String.IsNullOrEmpty(nmakeArguments) Then
              buildLogStream.Write("Command line = NMake {0}", _
                        nmakeArguments)
          Else 
              buildLogStream.Write("Command line = Nmake")
          End If
          
          buildLogStream.WriteLine()
          buildLogStream.Flush()
            
          logMutex.ReleaseMutex()
      
           ' Start the process.
           Console.WriteLine()
           Console.WriteLine("\nStarting Nmake command...")
           Console.WriteLine()
           nmakeProcess.Start()

           ' Start the asynchronous read of the error stream.
           nmakeProcess.BeginErrorReadLine()

           ' Start the asynchronous read of the output stream.
           nmakeProcess.BeginOutputReadLine()
    
           ' Let the nmake command run, collecting the output.
           nmakeProcess.WaitForExit()

           nmakeProcess.Close()
           buildLogStream.Close()
           logMutex.Dispose()
       End If
   End Sub 
   
    Private Shared Sub NMakeOutputDataHandler(sendingProcess As Object, _
       outLine As DataReceivedEventArgs)

        ' Collect the output, displaying it to the screen and 
        ' logging it to the output file.  Cancel the read
        ' operation when the maximum line limit is reached.

        If Not String.IsNullOrEmpty(outLine.Data) Then
            logMutex.WaitOne()

            currentLogLines = currentLogLines + 1
            If currentLogLines > maxLogLines Then
                
                ' Display the line to the console.
                ' Skip writing the line to the log file.
                Console.WriteLine("StdOut: {0}", outLine.Data)
            Else If currentLogLines = maxLogLines Then
                
                LogToFile("StdOut", "<Max build log limit reached!>", _
                    true)
    
                ' Stop reading the output streams.
                Dim p As Process = sendingProcess 
                If Not (p Is Nothing) Then
                    p.CancelOutputRead()
                    p.CancelErrorRead()
                End If
            Else 
                ' Write the line to the log file.
                LogToFile("StdOut", outLine.Data, true)
            End If

            logMutex.ReleaseMutex()
        End If
 
    End Sub 
   
   Private Shared Sub NMakeErrorDataHandler(sendingProcess As Object, _
        errLine As DataReceivedEventArgs)

      ' Collect the error output, displaying it to the screen and 
      ' logging it to the output file.  Cancel the error output
      ' read operation when the maximum line limit is reached.

        If Not String.IsNullOrEmpty(errLine.Data) Then
            logMutex.WaitOne()

            currentLogLines = currentLogLines + 1
            If currentLogLines > maxLogLines Then
                
                ' Display the line to the console.
                ' Skip writing the line to the log file.
                Console.WriteLine("StdErr: {0}", errLine.Data)
            Else If currentLogLines = maxLogLines Then
                
                LogToFile("StdErr", "<Max build log limit reached!>", _
                    true)
    
                ' Stop reading the output streams.
                Dim p As Process = sendingProcess 
                If Not (p Is Nothing) Then
                    p.CancelOutputRead()
                    p.CancelErrorRead()
                End If
            Else 
                ' Write the line to the log file.
                LogToFile("StdErr", errLine.Data, true)
            End If

            logMutex.ReleaseMutex()
        End If
 
    End Sub
   
    Private Shared Sub LogToFile(logPrefix As String, _
                                logText As String, _
                                echoToConsole As String)

        ' Write the specified line to the log file stream.
        Dim logString As StringBuilder = New StringBuilder()

        If Not String.IsNullOrEmpty(logPrefix) Then
                logString.AppendFormat("{0}> ", logPrefix)
        End If

        If Not String.IsNullOrEmpty(logText) Then
            logString.Append(logText)
        End If

        If Not buildLogStream Is Nothing Then
        
            buildLogStream.WriteLine("[{0}] {1}", _
                DateTime.Now.ToString(), logString.ToString())
            buildLogStream.Flush()
         End If
            
         If echoToConsole Then
            Console.WriteLine(logString.ToString())
         End If
  
    End Sub 
End Class

Комментарии

BeginOutputReadLine запускает асинхронную операцию чтения в потоке StandardOutput . CancelOutputRead завершает асинхронную операцию чтения.

После отмены можно возобновить асинхронные операции чтения, вызвав BeginOutputReadLine еще раз.

При вызове CancelOutputReadвыполняются все выполняемые операции StandardOutput чтения, а затем обработчик событий отключен. Все последующие перенаправленные выходные данные StandardOutput сохраняются в буфере. При повторном включении обработчика событий с вызовом BeginOutputReadLineсохраненные выходные данные отправляются обработчику событий и возобновляются асинхронные операции чтения. Чтобы изменить обработчик событий перед возобновлением асинхронных операций чтения, необходимо удалить существующий обработчик событий перед добавлением нового обработчика событий:

// At this point the DataReceivedEventHandler(OutputHandler1)   
// has executed a CancelOutputRead.  

// Remove the prior event handler.  
process.OutputDataReceived -=   
    new DataReceivedEventHandler(OutputHandler1);  

// Register a new event handler.  
process.OutputDataReceived +=   
    new DataReceivedEventHandler(OutputHandler2);  

// Call the corresponding BeginOutputReadLine.  
process.BeginOutputReadLine();  

Примечание

Нельзя смешивать асинхронные и синхронные операции чтения в перенаправленном StandardOutput потоке. После открытия перенаправленного потока объекта Process в асинхронном или синхронном режиме все дальнейшие операции чтения в этом потоке должны находиться в одном и том же режиме. Если отменить асинхронную операцию StandardOutput чтения, а затем снова выполнить чтение из потока, необходимо использовать для BeginOutputReadLine возобновления асинхронных операций чтения. Не используйте CancelOutputRead вызов синхронных методов чтения, таких StandardOutput как Read, ReadLineили ReadToEnd.

Применяется к

См. также раздел