Windows默认限制路径长度260字符,超长即抛IOException;启用长路径需同时满足:系统为Win10 1607+/Server 2016+且注册表LongPathsEnabled=1,.NET项目正确配置EnableLongPaths或enforceFIPolicy。

为什么 System.IO 操作超长路径会直接抛异常
Windows 默认限制路径总长度不超过 260 字符(MAX_PATH),C# 的 File.Copy、Directory.GetFiles 等方法底层调用 Win32 API,一旦路径(含盘符、冒号、斜杠、文件名)超过这个限制,就会直接抛出 IOException,错误信息通常是“路径太长”或“The specified path, file name, or both are too long”。这不是 .NET 的 bug,而是系统级默认策略——即使你用 \? 前缀手动构造长路径,.NET Framework 4.6.2 及更早版本也会在内部做截断或校验失败。
启用长路径支持的两个必要条件缺一不可
仅靠修改注册表或代码加前缀都不够,必须同时满足:
- 操作系统是 Windows 10 1607+ 或 Windows Server 2016+,且已启用组策略「启用 Win32 长路径」(对应注册表项
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlFileSystemLongPathsEnabled值为1) - .NET 应用需声明支持长路径:对 .NET Core 3.0+ / .NET 5+ 项目,在
.csproj中添加<enablelongpaths>true</enablelongpaths>;对 .NET Framework 4.6.2+,需在app.config的<runtime></runtime>节点下添加<enforcefipolicy enabled="false"></enforcefipolicy>并确保目标平台 ≥ 4.6.2
漏掉任一环节,\?C:erylongpath... 这种形式仍会被拒绝或静默截断。
\? 前缀不是万能的,这些地方必须手动处理
\? 是 Win32 的长路径前缀,但 .NET 的很多高阶 API(如 Directory.EnumerateFiles、Path.Combine)不会自动补上它,也不会识别已有前缀。常见陷阱包括:
-
Path.Combine(@"\?", "C:\a", "b")→ 错误拼成\?C:(多了一个),正确写法是Path.GetFullPath(@"\?" + Path.Combine("C:\a", "b"))或直接字符串拼接:@"\?" + fullPathWithoutPrefix -
Directory.GetFiles(@"\?C:dir")会成功,但Directory.GetFiles(@"\?C:dir", "*.txt")在某些旧版 .NET 中仍可能失败,建议改用Directory.EnumerateFiles+ 手动过滤 -
File.Move和File.Copy支持\?前缀,但源和目标都必须带前缀,且不能混用(比如源带前缀、目标不带)
推荐做法:封装一个长路径安全的文件操作辅助类
不要在业务逻辑里反复拼 ?,也不依赖用户手动开启所有配置。一个轻量封装能规避多数坑:
public static class LongPathHelper
{
public static string ToLongPath(string path) =>
path.StartsWith(@"\?") ? path : @"\?" + Path.GetFullPath(path);
<pre class="brush:php;toolbar:false;">public static void CopyFile(string source, string dest, bool overwrite = false)
{
File.Copy(ToLongPath(source), ToLongPath(dest), overwrite);
}
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern = "*")
{
return Directory.EnumerateFiles(ToLongPath(path), searchPattern);
}}
注意:该类不解决递归遍历深层嵌套目录时的栈溢出问题,若路径层级极深(如 > 100 层),仍需考虑迭代式遍历或使用 FindFirstFileEx 等底层 API。
最易被忽略的一点:即使启用了长路径,NTFS 卷必须格式化为支持长路径的版本(现代 Windows 默认满足),而某些网络共享、OneDrive 同步文件夹或第三方虚拟文件系统可能根本不识别 \? 前缀——这时异常不会消失,只是换了个报错方式。










