From e56b37f27c9f5f5619ac2fd6d57bb69db6e464f3 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Sun, 4 Oct 2026 10:27:40 +0000 Subject: [PATCH 1/2] Read .NET driver log files with shared access The Chrome, Edge, Firefox and IE log tests read the driver log right after driver.Quit() with File.ReadLines/ReadAllLines, which request exclusive read access. On Windows the driver process can still hold the file open for writing, so the read fails with "The process cannot access the file ... because it is being used by another process". Edge already retried for 10 seconds and still failed, so waiting does not help. Add a LogFile helper that opens the log with FileShare.ReadWrite | FileShare.Delete (as Troubleshooting/LoggingTest.cs already does), and a TryDelete for cleanup that ignores a still-locked file. Each call site is swapped on the same line, so gh-codeblock line ranges in the docs are unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01NUg261RgRsNLfjAXhj3FqP --- .../SeleniumDocs/Browsers/ChromeTest.cs | 10 +++--- .../dotnet/SeleniumDocs/Browsers/EdgeTest.cs | 4 +-- .../SeleniumDocs/Browsers/FirefoxTest.cs | 8 ++--- .../Browsers/InternetExplorerTest.cs | 4 +-- examples/dotnet/SeleniumDocs/LogFile.cs | 36 +++++++++++++++++++ 5 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 examples/dotnet/SeleniumDocs/LogFile.cs diff --git a/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs b/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs index 1d0cf7630ba5..4419abd8dfc2 100644 --- a/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs +++ b/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs @@ -25,7 +25,7 @@ public void Cleanup() driver?.Quit(); if (_logLocation != null && File.Exists(_logLocation)) { - File.Delete(_logLocation); + LogFile.TryDelete(_logLocation); } } @@ -108,7 +108,7 @@ public void LogsToFile() driver = new ChromeDriver(service); driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNotNull(lines.FirstOrDefault(line => line.Contains("Starting ChromeDriver"))); } @@ -123,7 +123,7 @@ public void LogsLevel() driver = new ChromeDriver(service); driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNotNull(lines.FirstOrDefault(line => line.Contains("[DEBUG]:"))); } @@ -140,7 +140,7 @@ public void ConfigureDriverLogs() driver = new ChromeDriver(service); driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); var regex = new Regex(@"\[\d\d-\d\d-\d\d\d\d \d\d:\d\d:\d\d\.\d+\]"); Assert.IsNotNull(lines.FirstOrDefault(line => regex.Matches(line).Count > 0)); } @@ -157,7 +157,7 @@ public void DisableBuildCheck() driver = new ChromeDriver(service); driver.Quit(); // Close the Service log file before reading var expected = "[WARNING]: You are using an unsupported command-line switch: --disable-build-check"; - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNotNull(lines.FirstOrDefault(line => line.Contains(expected))); } diff --git a/examples/dotnet/SeleniumDocs/Browsers/EdgeTest.cs b/examples/dotnet/SeleniumDocs/Browsers/EdgeTest.cs index 7020a3612666..dd1404c1d6a4 100644 --- a/examples/dotnet/SeleniumDocs/Browsers/EdgeTest.cs +++ b/examples/dotnet/SeleniumDocs/Browsers/EdgeTest.cs @@ -173,7 +173,7 @@ private static string[] ReadLogLines(string path) { try { - return File.ReadAllLines(path); + return LogFile.ReadLines(path); } catch (IOException) when (attempt < maxAttempts) { @@ -181,7 +181,7 @@ private static string[] ReadLogLines(string path) } } - return File.ReadAllLines(path); + return LogFile.ReadLines(path); } private string GetLogLocation() diff --git a/examples/dotnet/SeleniumDocs/Browsers/FirefoxTest.cs b/examples/dotnet/SeleniumDocs/Browsers/FirefoxTest.cs index dd2fae29493c..ad837ba211d5 100644 --- a/examples/dotnet/SeleniumDocs/Browsers/FirefoxTest.cs +++ b/examples/dotnet/SeleniumDocs/Browsers/FirefoxTest.cs @@ -22,7 +22,7 @@ public void Cleanup() driver?.Quit(); if (!String.IsNullOrEmpty(_logLocation) && File.Exists(_logLocation)) { - File.Delete(_logLocation); + LogFile.TryDelete(_logLocation); } if (_tempPath != null && Directory.Exists(_tempPath)) { @@ -65,7 +65,7 @@ public void LogsToFile() driver = new FirefoxDriver(service); driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNotNull(lines.FirstOrDefault(line => line.Contains("geckodriver INFO Listening on"))); } @@ -97,7 +97,7 @@ public void LogsLevel() driver = new FirefoxDriver(service); driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNotNull(lines.FirstOrDefault(line => line.Contains("Marionette\tDEBUG"))); } @@ -111,7 +111,7 @@ public void StopsTruncatingLogs() driver = new FirefoxDriver(service); driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNull(lines.FirstOrDefault(line => line.Contains(" ... "))); } diff --git a/examples/dotnet/SeleniumDocs/Browsers/InternetExplorerTest.cs b/examples/dotnet/SeleniumDocs/Browsers/InternetExplorerTest.cs index 087863299c73..97f46eb9e9bb 100644 --- a/examples/dotnet/SeleniumDocs/Browsers/InternetExplorerTest.cs +++ b/examples/dotnet/SeleniumDocs/Browsers/InternetExplorerTest.cs @@ -21,7 +21,7 @@ public void Cleanup() _driver?.Quit(); if (_logLocation != null && File.Exists(_logLocation)) { - File.Delete(_logLocation); + LogFile.TryDelete(_logLocation); } if (_tempPath != null && File.Exists(_tempPath)) { @@ -55,7 +55,7 @@ public void LogsLevel() _driver = new InternetExplorerDriver(service); _driver.Quit(); // Close the Service log file before reading - var lines = File.ReadLines(GetLogLocation()); + var lines = LogFile.ReadLines(GetLogLocation()); Assert.IsNotNull(lines.FirstOrDefault(line => line.Contains("Invalid capability setting: timeouts is type null"))); } diff --git a/examples/dotnet/SeleniumDocs/LogFile.cs b/examples/dotnet/SeleniumDocs/LogFile.cs new file mode 100644 index 000000000000..450ceee0467e --- /dev/null +++ b/examples/dotnet/SeleniumDocs/LogFile.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.IO; + +namespace SeleniumDocs +{ + // Driver log files can still be open by the driver process after Quit(), + // especially on Windows. Share the file instead of requesting exclusive access. + public static class LogFile + { + public static string[] ReadLines(string path) + { + using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, + FileShare.ReadWrite | FileShare.Delete); + using var reader = new StreamReader(stream); + var lines = new List(); + string line; + while ((line = reader.ReadLine()) != null) + { + lines.Add(line); + } + return lines.ToArray(); + } + + public static void TryDelete(string path) + { + try + { + File.Delete(path); + } + catch (IOException) + { + // Still held by the driver process; the OS temp directory cleans it up. + } + } + } +} From 9891d80dbb38cb163134f06374d81a78ddb9ffdc Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Sun, 4 Oct 2026 10:31:48 +0000 Subject: [PATCH 2/2] Retry locked driver log deletion and report leftovers The OS does not clean up %TEMP% on Windows, so a log that is still locked during test cleanup was left behind. Retry the delete for up to two seconds and write a warning to stderr if the file is still locked. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01NUg261RgRsNLfjAXhj3FqP --- examples/dotnet/SeleniumDocs/LogFile.cs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/dotnet/SeleniumDocs/LogFile.cs b/examples/dotnet/SeleniumDocs/LogFile.cs index 450ceee0467e..e63e51fba335 100644 --- a/examples/dotnet/SeleniumDocs/LogFile.cs +++ b/examples/dotnet/SeleniumDocs/LogFile.cs @@ -1,5 +1,7 @@ +using System; using System.Collections.Generic; using System.IO; +using System.Threading; namespace SeleniumDocs { @@ -23,13 +25,23 @@ public static string[] ReadLines(string path) public static void TryDelete(string path) { - try + const int maxAttempts = 10; + for (var attempt = 1; attempt <= maxAttempts; attempt++) { - File.Delete(path); - } - catch (IOException) - { - // Still held by the driver process; the OS temp directory cleans it up. + try + { + File.Delete(path); + return; + } + catch (IOException) when (attempt < maxAttempts) + { + // Still held by the driver process; give it time to exit. + Thread.Sleep(200); + } + catch (IOException e) + { + Console.Error.WriteLine($"Could not delete driver log {path}: {e.Message}"); + } } } }