Process.CancelErrorRead 메서드

정의

애플리케이션의 리디렉션된 StandardError 스트림에서 비동기 읽기 작업을 취소합니다.

public:
 void CancelErrorRead();
[System.Runtime.InteropServices.ComVisible(false)]
public void CancelErrorRead();
public void CancelErrorRead();
[<System.Runtime.InteropServices.ComVisible(false)>]
member this.CancelErrorRead : unit -> unit
member this.CancelErrorRead : unit -> unit
Public Sub CancelErrorRead ()
특성

예외

StandardError 비동기 읽기 작업에 스트림을 사용할 수 없습니다.

예제

다음 예제에서는 사용자가 제공한 인수를 nmake 사용하여 명령을 시작합니다. 오류 및 출력 스트림은 비동기적으로 읽습니다. 수집된 텍스트 줄이 콘솔에 표시되고 로그 파일에 기록됩니다. 명령 출력이 지정된 줄 수를 초과하면 비동기 읽기 작업이 취소됩니다.

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 static variables shared by class methods.
let mutable buildLogStream = Unchecked.defaultof<StreamWriter>
let logMutex = new Mutex()
let mutable maxLogLines = 25
let mutable currentLogLines = 0

let logToFile logPrefix logText echoToConsole =
    // Write the specified line to the log file stream.
    let logString = StringBuilder()

    if String.IsNullOrEmpty logPrefix |> not then
        logString.AppendFormat $"{logPrefix}> " |> ignore

    if String.IsNullOrEmpty logPrefix |> not then
        logString.AppendFormat $"{logPrefix}> " |> ignore

    if String.IsNullOrEmpty logText |> not then
        logString.Append logText |> ignore

    if isNull buildLogStream |> not then
        buildLogStream.WriteLine $"[{DateTime.Now}] {logString}"
        buildLogStream.Flush()

    if echoToConsole then
        printfn $"{logString}"

let nMakeOutputDataHandler (sendingProcess: obj) (outLine: 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 String.IsNullOrEmpty outLine.Data |> not then
        logMutex.WaitOne() |> ignore

        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)
        elif currentLogLines = maxLogLines then
            logToFile "StdOut" "<Max build log limit reached!>" true

            // Stop reading the output streams.
            match sendingProcess with
            | :? Process as p ->
                p.CancelOutputRead()
                p.CancelErrorRead()
            | _ -> ()
        else
            // Write the line to the log file.
            logToFile "StdOut" outLine.Data true

        logMutex.ReleaseMutex()

let nMakeErrorDataHandler (sendingProcess: obj) (errLine: DataReceivedEventArgs) =
    // 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 |> not then
        logMutex.WaitOne() |> ignore

        currentLogLines <- currentLogLines + 1

        if currentLogLines > maxLogLines then
            // Display the error line to the console.
            // Skip writing the line to the log file.
            printfn $"StdErr: {errLine.Data}"
        elif currentLogLines = maxLogLines then
            logToFile "StdErr" "<Max build log limit reached!>" true

            // Stop reading the output streams
            match sendingProcess with
            | :? Process as p ->
                p.CancelErrorRead()
                p.CancelOutputRead()
            | _ -> ()
        else
            // Write the line to the log file.
            logToFile "StdErr" errLine.Data true

        logMutex.ReleaseMutex()

let redirectNMakeCommandStreams () =
    // Get the input nmake command-line arguments.
    printfn "Enter the NMake command line arguments (@commandfile or /f makefile, etc):"
    let nmakeArguments = stdin.ReadLine()

    printfn "Enter max line limit for log file (default is 25):"
    let inputText = Console.ReadLine()

    if String.IsNullOrEmpty inputText |> not then
        if Int32.TryParse(inputText, &maxLogLines) |> not then
            maxLogLines <- 25

    printfn $"Output beyond {maxLogLines} lines will be ignored."

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

    // Build the nmake command argument list.
    if String.IsNullOrEmpty nmakeArguments |> not then
        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.AddHandler(DataReceivedEventHandler nMakeOutputDataHandler)

    // Redirect the error output of the nmake command.
    nmakeProcess.StartInfo.RedirectStandardError <- true
    nmakeProcess.ErrorDataReceived.AddHandler(DataReceivedEventHandler nMakeErrorDataHandler)

    logMutex.WaitOne() |> ignore

    currentLogLines <- 0

    // Write a header to the log file.
    let buildLogFile = "NmakeCmd.Txt"

    try
        buildLogStream <- new StreamWriter(buildLogFile, true)
    with e ->
        printfn $"Could not open output file {buildLogFile}"
        printfn $"Exception = {e}"
        printfn $"{e.Message}"

        buildLogStream <- null

    if isNull buildLogStream |> not then
        printfn $"Nmake output logged to {buildLogFile}"

        buildLogStream.WriteLine()
        buildLogStream.WriteLine DateTime.Now

        if String.IsNullOrEmpty nmakeArguments |> not then
            buildLogStream.Write $"Command line = NMake {nmakeArguments}"
        else
            buildLogStream.Write "Command line = Nmake"

        buildLogStream.WriteLine()
        buildLogStream.Flush()

        logMutex.ReleaseMutex()

        // Start the process.
        Console.WriteLine("\n\nStarting Nmake command...\n")
        nmakeProcess.Start() |> ignore

        // 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()
' 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

설명

BeginErrorReadLine 는 스트림에서 비동기 읽기 작업을 시작합니다 StandardError . CancelErrorRead 는 비동기 읽기 작업을 종료합니다.

취소한 후 다시 호출 BeginErrorReadLine 하여 비동기 읽기 작업을 다시 시작할 수 있습니다.

호출 CancelErrorRead하면 진행 중인 모든 읽기 작업이 StandardError 완료되고 이벤트 처리기가 비활성화됩니다. 리디렉션된 모든 출력 StandardError 이 손실됩니다. 호출 BeginErrorReadLine을 사용하여 이벤트 처리기를 다시 사용하도록 설정하면 비동기 읽기 작업이 다시 시작됩니다. 비동기 읽기 작업을 다시 시작하기 전에 이벤트 처리기를 변경하려면 새 이벤트 처리기를 추가하기 전에 기존 이벤트 처리기를 제거해야 합니다.

// At this point the DataReceivedEventHandler(ErrorHandler1)
// has executed a CancelErrorRead.

// Remove the prior event handler.
process.ErrorDataReceived -=
    new DataReceivedEventHandler(ErrorHandler1);

// Register a new event handler.
process.ErrorDataReceived +=
    new DataReceivedEventHandler(ErrorHandler2);

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

메모

리디렉션된 StandardError 스트림에서는 비동기 및 동기 읽기 작업을 혼합할 수 없습니다. 리디렉션된 스트림 Process 이 비동기 또는 동기 모드로 열리면 해당 스트림에 대한 모든 추가 읽기 작업이 동일한 모드에 있어야 합니다. 비동기 읽기 작업을 StandardError 취소한 다음 스트림에서 다시 읽어야 하는 경우 비동기 읽기 작업을 다시 시작하는 데 사용해야 BeginErrorReadLine 합니다. 와 같은 ReadLineReadReadToEnd동기식 읽기 메서드 StandardError 에 대한 호출을 따르지 CancelErrorRead 마세요.

적용 대상

추가 정보