.NET 4.8类库遇长路径异常但WinForms项目正常的问题求助
解决.NET 4.8类库长路径调用上下文异常问题
核心原因
问题出在宿主进程的长路径感知状态:WinForms项目默认通过模板清单启用长路径感知,而NUnit-x86.exe、原生C++ COM宿主这类进程默认未开启该特性,导致.NET IO方法仍受MAX_PATH限制——即便类库本身配置了清单或修改了注册表,也无法覆盖宿主进程的限制。
可行解决方案
1. 在类库中强制启用长路径支持(推荐)
在类库的初始化逻辑(比如测试类的静态构造函数、SetUp方法)中添加以下开关,强制.NET框架禁用旧路径处理逻辑,绕过MAX_PATH限制:
static Class1() { // 禁用旧版路径处理逻辑 AppContext.SetSwitch("Switch.System.IO.UseLegacyPathHandling", false); // 解除长路径阻塞限制 AppContext.SetSwitch("Switch.System.IO.BlockLongPaths", false); }
修改测试代码后,即使宿主进程未启用长路径感知,类库的IO操作也能正常处理长路径。
2. 为宿主进程添加长路径感知清单
针对NUnit-x86.exe:
找到NUnit安装目录下的nunit-x86.exe,创建同名的nunit-x86.exe.manifest文件,内容如下:<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> </windowsSettings> </application> </assembly>保存后重启NUnit,测试即可正常运行。
针对原生C++ COM宿主:
在C++项目的应用程序清单文件中添加<longPathAware>true</longPathAware>节点,重新编译宿主程序。
3. 手动使用\\?\前缀并调用Win32 API(兜底方案)
如果以上方法无效,可直接调用Win32 API替代.NET内置IO方法,确保绕开MAX_PATH限制:
using System.Runtime.InteropServices; // 导入Win32 API [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern int GetFullPathNameW( string lpFileName, int nBufferLength, StringBuilder lpBuffer, IntPtr lpFilePart); // 获取长路径的目录名示例 public static string GetLongPathDirectoryName(string path) { // 转换为\\?\前缀格式 string longPathPrefix = @"\\?\"; string formattedPath = path.StartsWith(longPathPrefix) ? path : longPathPrefix + path; StringBuilder buffer = new StringBuilder(260); GetFullPathNameW(formattedPath, buffer.Capacity, buffer, IntPtr.Zero); // 提取目录部分 string fullPath = buffer.ToString(); return Path.GetDirectoryName(fullPath)?.Replace(longPathPrefix, ""); }
使用时直接调用GetLongPathDirectoryName(strPath)即可替代Path.GetDirectoryName。
注意事项
- 需确保系统版本为Windows 10 1607+或Windows Server 2016+,且注册表项
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled(DWORD值为1)已正确设置。 - 使用
\\?\前缀时,路径必须是绝对路径,不能包含..这类相对路径符号,C#中需用@前缀或双反斜杠转义路径。
内容的提问来源于stack exchange,提问作者Dan G
相关产品推荐
相关产品推荐

