Skip to content

Commit 72d12cd

Browse files
committed
Reading output through async events.
1 parent fb64aba commit 72d12cd

File tree

3 files changed

+45
-148
lines changed

3 files changed

+45
-148
lines changed

dotnet/src/webdriver/DriverProcessStartedEventArgs.cs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
using System;
2121
using System.Diagnostics;
22-
using System.IO;
2322

2423
namespace OpenQA.Selenium;
2524

@@ -41,31 +40,10 @@ public DriverProcessStartedEventArgs(Process driverProcess)
4140
}
4241

4342
this.ProcessId = driverProcess.Id;
44-
if (driverProcess.StartInfo.RedirectStandardOutput && !driverProcess.StartInfo.UseShellExecute)
45-
{
46-
this.StandardOutputStreamReader = driverProcess.StandardOutput;
47-
}
48-
49-
if (driverProcess.StartInfo.RedirectStandardError && !driverProcess.StartInfo.UseShellExecute)
50-
{
51-
this.StandardErrorStreamReader = driverProcess.StandardError;
52-
}
5343
}
5444

5545
/// <summary>
5646
/// Gets the unique ID of the driver executable process.
5747
/// </summary>
5848
public int ProcessId { get; }
59-
60-
/// <summary>
61-
/// Gets a <see cref="StreamReader"/> object that can be used to read the contents
62-
/// printed to <c>stdout</c> by a driver service process.
63-
/// </summary>
64-
public StreamReader? StandardOutputStreamReader { get; }
65-
66-
/// <summary>
67-
/// Gets a <see cref="StreamReader"/> object that can be used to read the contents
68-
/// printed to <c>stderr</c> by a driver service process.
69-
/// </summary>
70-
public StreamReader? StandardErrorStreamReader { get; }
7149
}

dotnet/src/webdriver/DriverService.cs

Lines changed: 26 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
using System.IO;
2626
using System.Net;
2727
using System.Net.Http;
28-
using System.Threading;
2928
using System.Threading.Tasks;
3029
using OpenQA.Selenium.Internal.Logging;
3130

@@ -253,8 +252,11 @@ public void Start()
253252
this.driverServiceProcess.StartInfo.UseShellExecute = false;
254253
this.driverServiceProcess.StartInfo.CreateNoWindow = this.HideCommandPromptWindow;
255254

256-
this.driverServiceProcess.StartInfo.RedirectStandardOutput = this.WriteDriverLogToConsole;
257-
this.driverServiceProcess.StartInfo.RedirectStandardError = this.WriteDriverLogToConsole;
255+
this.driverServiceProcess.StartInfo.RedirectStandardOutput = true;
256+
this.driverServiceProcess.StartInfo.RedirectStandardError = true;
257+
258+
this.driverServiceProcess.OutputDataReceived += (s, e) => this.OnDriverProcessDataReceived(s, e, isError: false);
259+
this.driverServiceProcess.ErrorDataReceived += (s, e) => this.OnDriverProcessDataReceived(s, e, isError: true);
258260

259261
DriverProcessStartingEventArgs eventArgs = new DriverProcessStartingEventArgs(this.driverServiceProcess.StartInfo);
260262
this.OnDriverProcessStarting(eventArgs);
@@ -264,6 +266,9 @@ public void Start()
264266
DriverProcessStartedEventArgs processStartedEventArgs = new DriverProcessStartedEventArgs(this.driverServiceProcess);
265267
this.OnDriverProcessStarted(processStartedEventArgs);
266268

269+
this.driverServiceProcess.BeginOutputReadLine();
270+
this.driverServiceProcess.BeginErrorReadLine();
271+
267272
if (!serviceAvailable)
268273
{
269274
throw new WebDriverException($"Cannot start the driver service on {this.ServiceUrl}");
@@ -318,27 +323,28 @@ protected virtual void OnDriverProcessStarted(DriverProcessStartedEventArgs even
318323
throw new ArgumentNullException(nameof(eventArgs), "eventArgs must not be null");
319324
}
320325

321-
if (this.WriteDriverLogToConsole && eventArgs.StandardOutputStreamReader != null)
326+
this.DriverProcessStarted?.Invoke(this, eventArgs);
327+
}
328+
329+
/// <summary>
330+
/// Handles the output and error data received from the driver process.
331+
/// </summary>
332+
/// <param name="sender">The sender of the event.</param>
333+
/// <param name="args">The data received event arguments.</param>
334+
/// <param name="isError">A value indicating whether the data received is from the error stream.</param>
335+
protected virtual void OnDriverProcessDataReceived(object sender, DataReceivedEventArgs args, bool isError)
336+
{
337+
if (string.IsNullOrEmpty(args.Data))
338+
return;
339+
340+
if (this.WriteDriverLogToConsole && !isError && _logger.IsEnabled(LogEventLevel.Info))
322341
{
323-
var stdoutThread = new Thread(() => ReadStreamSync(eventArgs.StandardOutputStreamReader, "stdout"))
324-
{
325-
IsBackground = true,
326-
Name = "DriverService-stdout"
327-
};
328-
stdoutThread.Start();
342+
_logger.Info(args.Data);
329343
}
330-
331-
if (this.WriteDriverLogToConsole && eventArgs.StandardErrorStreamReader != null)
344+
if (this.WriteDriverLogToConsole && isError && _logger.IsEnabled(LogEventLevel.Error))
332345
{
333-
var stderrThread = new Thread(() => ReadStreamSync(eventArgs.StandardErrorStreamReader, "stderr"))
334-
{
335-
IsBackground = true,
336-
Name = "DriverService-stderr"
337-
};
338-
stderrThread.Start();
346+
_logger.Error(args.Data);
339347
}
340-
341-
this.DriverProcessStarted?.Invoke(this, eventArgs);
342348
}
343349

344350
/// <summary>
@@ -419,69 +425,4 @@ private bool WaitForServiceInitialization()
419425

420426
return isInitialized;
421427
}
422-
423-
private void ReadStreamSync(StreamReader reader, string streamType)
424-
{
425-
try
426-
{
427-
string? line;
428-
while ((line = reader.ReadLine()) != null)
429-
{
430-
if (streamType.Equals("stdout", StringComparison.OrdinalIgnoreCase))
431-
{
432-
if (_logger.IsEnabled(LogEventLevel.Info))
433-
{
434-
_logger.Info(line);
435-
}
436-
}
437-
else
438-
{
439-
if (_logger.IsEnabled(LogEventLevel.Error))
440-
{
441-
_logger.Error(line);
442-
}
443-
}
444-
}
445-
}
446-
catch (Exception ex)
447-
{
448-
if (_logger.IsEnabled(LogEventLevel.Error))
449-
{
450-
_logger.Error($"Error reading stream: {ex}");
451-
}
452-
}
453-
}
454-
455-
private async Task ReadStreamAsync(StreamReader reader, string streamType)
456-
{
457-
try
458-
{
459-
string? line;
460-
while ((line = await reader.ReadLineAsync()) != null)
461-
{
462-
if (streamType.Equals("stdout", StringComparison.OrdinalIgnoreCase))
463-
{
464-
if (_logger.IsEnabled(LogEventLevel.Info))
465-
{
466-
_logger.Info(line);
467-
}
468-
}
469-
else
470-
{
471-
if (_logger.IsEnabled(LogEventLevel.Error))
472-
{
473-
_logger.Error(line);
474-
}
475-
}
476-
}
477-
}
478-
catch (Exception ex)
479-
{
480-
if (_logger.IsEnabled(LogEventLevel.Error))
481-
{
482-
_logger.Error($"Error reading stream: {ex}");
483-
}
484-
}
485-
}
486-
487428
}

dotnet/src/webdriver/Firefox/FirefoxDriverService.cs

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919

2020
using OpenQA.Selenium.Internal;
2121
using System;
22+
using System.Diagnostics;
2223
using System.Globalization;
2324
using System.IO;
2425
using System.Text;
25-
using System.Threading;
2626
using OpenQA.Selenium.Internal.Logging;
2727

2828
namespace OpenQA.Selenium.Firefox;
@@ -196,11 +196,11 @@ protected override string CommandLineArguments
196196
}
197197

198198
/// <summary>
199-
/// Handles the event when the driver service process is starting.
199+
/// Called when the driver process is starting. This method sets up log file writing if a log path is specified.
200200
/// </summary>
201201
/// <param name="eventArgs">The event arguments containing information about the driver service process.</param>
202202
/// <remarks>
203-
/// This method initializes a log writer if a log path is specified and redirects output streams to capture logs.
203+
/// This method initializes a log writer if a log path is specified.
204204
/// </remarks>
205205
protected override void OnDriverProcessStarting(DriverProcessStartingEventArgs eventArgs)
206206
{
@@ -214,46 +214,37 @@ protected override void OnDriverProcessStarting(DriverProcessStartingEventArgs e
214214
}
215215

216216
logWriter = new StreamWriter(this.LogPath, append: true) { AutoFlush = true };
217-
218-
eventArgs.DriverServiceProcessStartInfo.RedirectStandardOutput = true;
219-
eventArgs.DriverServiceProcessStartInfo.RedirectStandardError = true;
220217
}
221218

222219
base.OnDriverProcessStarting(eventArgs);
223220
}
224221

225222
/// <summary>
226-
/// Handles the event when the driver process has started.
223+
/// Handles the output and error data received from the driver process and sends it to the log writer if available.
227224
/// </summary>
228-
/// <param name="eventArgs">The event arguments containing information about the started driver process.</param>
229-
/// <remarks>
230-
/// This method reads the output and error streams asynchronously and writes them to the log file if available.
231-
/// </remarks>
232-
protected override void OnDriverProcessStarted(DriverProcessStartedEventArgs eventArgs)
225+
/// <param name="sender">The sender of the event.</param>
226+
/// <param name="args">The data received event arguments.</param>
227+
/// <param name="isError">A value indicating whether the data received is from the error stream.</param>
228+
protected override void OnDriverProcessDataReceived(object sender, DataReceivedEventArgs args, bool isError)
233229
{
234-
if (!string.IsNullOrEmpty(this.LogPath) && eventArgs.StandardOutputStreamReader != null)
230+
if (string.IsNullOrEmpty(args.Data))
231+
return;
232+
233+
if (!string.IsNullOrEmpty(this.LogPath))
235234
{
236-
var stdoutThread = new Thread(() => ReadStream(eventArgs.StandardOutputStreamReader))
235+
if (logWriter != null)
237236
{
238-
IsBackground = true,
239-
Name = "FirefoxDriverService-stdout"
240-
};
241-
stdoutThread.Start();
237+
logWriter.WriteLine(args.Data);
238+
logWriter.Flush();
239+
}
242240
}
243-
244-
if (!string.IsNullOrEmpty(this.LogPath) && eventArgs.StandardErrorStreamReader != null)
241+
else
245242
{
246-
var stderrThread = new Thread(() => ReadStream(eventArgs.StandardErrorStreamReader))
247-
{
248-
IsBackground = true,
249-
Name = "FirefoxDriverService-stderr"
250-
};
251-
stderrThread.Start();
243+
base.OnDriverProcessDataReceived(sender, args, isError);
252244
}
253-
254-
base.OnDriverProcessStarted(eventArgs);
255245
}
256246

247+
257248
/// <summary>
258249
/// Disposes of the resources used by the <see cref="FirefoxDriverService"/> instance.
259250
/// </summary>
@@ -353,17 +344,4 @@ private static string FirefoxDriverServiceFileName()
353344

354345
return fileName;
355346
}
356-
357-
private void ReadStream(StreamReader reader)
358-
{
359-
string line;
360-
while ((line = reader.ReadLine()) != null)
361-
{
362-
if (logWriter != null)
363-
{
364-
logWriter.WriteLine(line);
365-
logWriter.Flush();
366-
}
367-
}
368-
}
369347
}

0 commit comments

Comments
 (0)