diff --git a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs
new file mode 100644
index 00000000000000..015ba30b6ad7c1
--- /dev/null
+++ b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.DotNet.XUnitExtensions;
+using System.Diagnostics;
+using System.Diagnostics.Eventing.Reader;
+using System.Linq;
+using System.Security;
+using System.ServiceProcess;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace System.IO.Tests
+{
+ public partial class EncryptDecrypt
+ {
+ partial void EnsureEFSServiceStarted()
+ {
+ try
+ {
+ using var sc = new ServiceController("EFS");
+ _output.WriteLine($"EFS service is: {sc.Status}");
+ if (sc.Status != ServiceControllerStatus.Running)
+ {
+ _output.WriteLine("Trying to start EFS service");
+ sc.Start();
+ _output.WriteLine($"EFS service is now: {sc.Status}");
+ }
+ }
+ catch (Exception e)
+ {
+ _output.WriteLine(e.ToString());
+ }
+ }
+
+ partial void LogEFSDiagnostics()
+ {
+ int hours = 1; // how many hours to look backwards
+ string query = @$"
+
+
+
+
+
+
+ *[System[TimeCreated[timediff(@SystemTime) >= {hours * 60 * 60 * 1000L}]]]
+
+
+ ";
+
+ var eventQuery = new EventLogQuery("System", PathType.LogName, query);
+
+ using var eventReader = new EventLogReader(eventQuery);
+
+ EventRecord record = eventReader.ReadEvent();
+ var garbage = new string[] { "Background Intelligent", "Intel", "Defender", "Intune", "BITS", "NetBT"};
+
+ _output.WriteLine("===== Dumping recent relevant events: =====");
+ while (record != null)
+ {
+ string description = "";
+ try
+ {
+ description = record.FormatDescription();
+ }
+ catch (EventLogException) { }
+
+ if (!garbage.Any(term => description.Contains(term, StringComparison.OrdinalIgnoreCase)))
+ {
+ _output.WriteLine($"{record.TimeCreated} {record.ProviderName} [{record.LevelDisplayName} {record.Id}] {description.Replace("\r\n", " ")}");
+ }
+
+ record = eventReader.ReadEvent();
+ }
+
+ _output.WriteLine("==== Finished dumping =====");
+ }
+ }
+}
diff --git a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs
index 12299fad33fcf5..c4d34c320668ef 100644
--- a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs
+++ b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs
@@ -1,17 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Microsoft.DotNet.XUnitExtensions;
using System.Diagnostics;
+using System.Diagnostics.Eventing.Reader;
using System.Security;
+using System.ServiceProcess;
using Xunit;
+using Xunit.Abstractions;
namespace System.IO.Tests
{
[ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
- public class EncryptDecrypt : FileSystemTest
+ public partial class EncryptDecrypt : FileSystemTest
{
+ private readonly ITestOutputHelper _output;
+
+ public EncryptDecrypt(ITestOutputHelper output)
+ {
+ _output = output;
+ }
+
[Fact]
- public static void NullArg_ThrowsException()
+ public void NullArg_ThrowsException()
{
AssertExtensions.Throws("path", () => File.Encrypt(null));
AssertExtensions.Throws("path", () => File.Decrypt(null));
@@ -19,7 +30,7 @@ public static void NullArg_ThrowsException()
[SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp)]
[Fact]
- public static void EncryptDecrypt_NotSupported()
+ public void EncryptDecrypt_NotSupported()
{
Assert.Throws(() => File.Encrypt("path"));
Assert.Throws(() => File.Decrypt("path"));
@@ -29,7 +40,8 @@ public static void EncryptDecrypt_NotSupported()
// because EFS (Encrypted File System), its underlying technology, is not available on these operating systems.
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsHomeEdition))]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void EncryptDecrypt_Read()
+ [OuterLoop] // Occasional failures: https://github.com/dotnet/runtime/issues/12339
+ public void EncryptDecrypt_Read()
{
string tmpFileName = Path.GetTempFileName();
string textContentToEncrypt = "Content to encrypt";
@@ -39,6 +51,8 @@ public static void EncryptDecrypt_Read()
string fileContentRead = File.ReadAllText(tmpFileName);
Assert.Equal(textContentToEncrypt, fileContentRead);
+ EnsureEFSServiceStarted();
+
try
{
File.Encrypt(tmpFileName);
@@ -48,7 +62,13 @@ public static void EncryptDecrypt_Read()
{
// Ignore ERROR_NOT_FOUND 1168 (0x490). It is reported when EFS is disabled by domain policy.
// Ignore ERROR_NO_USER_KEYS (0x1776). This occurs when no user key exists to encrypt with.
- return;
+ throw new SkipTestException($"Encrypt not available. Error 0x{e.HResult:X}");
+ }
+ catch (IOException e)
+ {
+ _output.WriteLine($"Encrypt failed with {e.Message} 0x{e.HResult:X}");
+ LogEFSDiagnostics();
+ throw;
}
Assert.Equal(fileContentRead, File.ReadAllText(tmpFileName));
@@ -63,5 +83,9 @@ public static void EncryptDecrypt_Read()
File.Delete(tmpFileName);
}
}
+
+ partial void EnsureEFSServiceStarted(); // no-op on Unix
+
+ partial void LogEFSDiagnostics(); // no-op on Unix currently
}
}
diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj
index 7c219c593107bf..83f7bf47ea78e0 100644
--- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj
+++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj
@@ -76,6 +76,7 @@
+