You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 13:34:37