Process.CancelOutputRead 方法

定義

在應用程式的重新導向 StandardOutput 資料流上取消非同步讀取作業。

C#
public void CancelOutputRead ();
C#
[System.Runtime.InteropServices.ComVisible(false)]
public void CancelOutputRead ();
屬性

例外狀況

未因非同步讀取作業之故開啟 StandardOutput 資料流。

範例

下列範例會 nmake 以使用者提供的自變數啟動 命令。 錯誤和輸出數據流會以異步方式讀取;收集的文字行會顯示至主控台,以及寫入記錄檔。 如果命令輸出超過指定的行數,則會取消異步讀取作業。

C#
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());
            }
        }
    }
}

備註

BeginOutputReadLine 在數據流上 StandardOutput 啟動異步讀取作業。 CancelOutputRead 結束異步讀取作業。

取消之後,您可以再次呼叫 BeginOutputReadLine 來繼續異步讀取作業。

當您呼叫 CancelOutputRead時,會完成 的所有進行中讀取作業 StandardOutput ,然後停用事件處理程式。 所有進一步重新導向的輸出 StandardOutput 都會儲存在緩衝區中。 如果您使用呼叫 BeginOutputReadLine重新啟用事件處理程式,則會將儲存的輸出傳送至事件處理程式,並繼續異步讀取作業。 如果您想要在繼續異步讀取作業之前變更事件處理程式,您必須先移除現有的事件處理程式,才能新增事件處理程式:

C#
// 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 的呼叫,例如 ReadReadLineReadToEnd

適用於

產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

另請參閱