Process.CancelErrorRead Метод
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Отменяет асинхронную операцию чтения в перенаправленном StandardError потоке приложения.
public:
void CancelErrorRead();
public void CancelErrorRead();
[System.Runtime.InteropServices.ComVisible(false)]
public void CancelErrorRead();
member this.CancelErrorRead : unit -> unit
[<System.Runtime.InteropServices.ComVisible(false)>]
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();
Note
Вы не можете смешивать асинхронные и синхронные операции чтения в перенаправленном StandardError потоке. После открытия перенаправленного потока в Process асинхронном или синхронном режиме все дальнейшие операции чтения в этом потоке должны находиться в одном и том же режиме. Если отменить асинхронную операцию StandardError чтения, а затем снова необходимо выполнить чтение из потока, необходимо использовать BeginErrorReadLine для возобновления асинхронных операций чтения. Не следуйте CancelErrorRead вызову синхронных методов чтения, таких StandardError как Read, ReadLineили ReadToEnd.