diff --git a/CHANGELOG.md b/CHANGELOG.md
index f07308e85..000dec9c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,8 +3,9 @@
## Improvements:
## Bug fixes:
+* Fix: GenerateFeatureFileCodeBehindTask fails with misleading DirectoryNotFoundException when ndjson output path exceeds Windows MAX_PATH (260)
-*Contributors of this release (in alphabetical order):*
+*Contributors of this release (in alphabetical order):* @clrudolphi
# v3.3.4 - 2026-03-23
diff --git a/Reqnroll.Tools.MsBuild.Generation/GeneratedFileWriter.cs b/Reqnroll.Tools.MsBuild.Generation/GeneratedFileWriter.cs
index 11bce6031..bd1dc6017 100644
--- a/Reqnroll.Tools.MsBuild.Generation/GeneratedFileWriter.cs
+++ b/Reqnroll.Tools.MsBuild.Generation/GeneratedFileWriter.cs
@@ -1,12 +1,10 @@
+using System;
using System.IO;
using System.Text;
using Reqnroll.Utils;
namespace Reqnroll.Tools.MsBuild.Generation;
-///
-/// This class is going to be obsolete once we implement MsBuild level up-to-date checks.
-///
public class GeneratedFileWriter(IReqnrollTaskLoggingHelper log)
{
public void WriteGeneratedFile(string outputPath, string generatedFileContent)
@@ -17,13 +15,15 @@ public void WriteGeneratedFile(string outputPath, string generatedFileContent)
public void DeleteGeneratedFile(string outputPath)
{
- if (!File.Exists(outputPath))
+ var path = ChangePathToSupportLongPaths(outputPath);
+
+ if (!File.Exists(path))
return;
log.LogTaskDiagnosticMessage($"Deleting {outputPath}");
try
{
- File.Delete(outputPath);
+ File.Delete(path);
}
catch (IOException ex)
{
@@ -34,12 +34,40 @@ public void DeleteGeneratedFile(string outputPath)
private void WriteFile(string filePath, string content)
{
string directoryPath = Path.GetDirectoryName(filePath);
- if (directoryPath != null && !Directory.Exists(directoryPath))
+ var longDirPath = ChangePathToSupportLongPaths(directoryPath);
+ if (!string.IsNullOrEmpty(longDirPath) && !Directory.Exists(longDirPath))
+ {
+ Directory.CreateDirectory(longDirPath);
+ }
+ var longPath = ChangePathToSupportLongPaths(filePath);
+ WriteAllTextWithRetry(longPath, content, Encoding.UTF8);
+ }
+
+ private static string ChangePathToSupportLongPaths(string path)
+ {
+ if (string.IsNullOrWhiteSpace(path))
+ return path;
+
+ string fullPath = Path.GetFullPath(path);
+
+ // Cross-platform: only apply extended syntax on Windows.
+ if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(
+ System.Runtime.InteropServices.OSPlatform.Windows))
{
- Directory.CreateDirectory(directoryPath);
+ return fullPath;
}
- WriteAllTextWithRetry(filePath, content, Encoding.UTF8);
+ // Already device/extended syntax.
+ if (fullPath.StartsWith(@"\\?\", StringComparison.Ordinal) ||
+ fullPath.StartsWith(@"\\.\", StringComparison.Ordinal))
+ return fullPath;
+
+ // UNC longDirPath.
+ if (fullPath.StartsWith(@"\\", StringComparison.Ordinal))
+ return @"\\?\UNC\" + fullPath.Substring(2);
+
+ // Drive-qualified longDirPath.
+ return @"\\?\" + fullPath;
}
///