【问题标题】:Why Path.GetDirectoryName function has to be dependent on 260 chars limit为什么 Path.GetDirectoryName 函数必须依赖于 260 个字符的限制
【发布时间】:2014-05-11 22:33:35
【问题描述】:
public static void Main()
{
    // testing file name
    var fileName =
        "\\\\server7\\EmailAttachments\\myfolder\\abc\\2012\\1126\\e85c6b82-edc5-4ce1-9ad0-8025b92d0105-o.dom=38c55279fe168c290fb2b06a312b5d88&b=6f54a59ce903eeaff197f82937de4012.dom=38c55279fe168c290fb2b06a312b5d88&b=6f54a59ce903eeaff197f82937de4012=6f54a59ce903eeaff197f82937de4012.dom=38c55279fe168c290fb2b06a312b5d88&b=6f54a59ce903eeaff197f82937de4012";

    var directory = fileName.GetDirectory();
}

   public static string GetDirectory(this string fullyQualifiedFileName)
     {
         return Path.GetDirectoryName(fullyQualifiedFileName); // throwing exception here
     }

遇到异常

System.IO.PathTooLongException 发生 HResult=-2147024690
Message=指定的路径、文件名或两者都太长。完全 限定文件名必须少于 260 个字符,并且 目录名称必须少于 248 个字符。来源=mscorlib
堆栈跟踪: 在 System.IO.Path.NormalizePath(字符串路径,布尔 fullCheck,Int32 maxPathLength,布尔 expandShortPaths) 在 System.IO.Path.GetDirectoryName(字符串路径) 在 f:\Practice 中的 Sameer.FilePathExtension.GetDirectory(StringfullyQualifiedFileName) Projects\Sameer\Sameer\FilePathExtension.cs:第 137 行 InnerException:

我想知道为什么 GetDirectoryName 必须依赖于路径或文件名字符限制。

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    如 msdn 网站中所述

    "完整路径不得超过 260 个字符以保持兼容性 使用 Windows 操作系统”

    http://msdn.microsoft.com/en-us/library/system.io.pathtoolongexception(v=vs.100).aspx

    您可以在此处找到其背后的原因,如以下链接中所述。

    另一个问题是暴露会导致不一致的行为 长路径支持。带有 \?\ 前缀的长路径可以在大多数情况下使用 文件相关的 Windows API,但不是所有的 Windows API。为了 例如,LoadLibrary,它将一个模块映射到 调用进程,如果文件名长于 MAX_PATH 则失败。所以 这意味着 MoveFile 将允许您将 DLL 移动到这样的位置 它的路径超过 260 个字符,但是当您尝试加载 DLL,它会失败。整个 Windows 都有类似的例子 蜜蜂;存在一些解决方法,但它们是根据具体情况而定的。

    另一个被认为是疼痛因素的因素是 与其他基于 Windows 的应用程序和 Windows 的兼容性 shell 本身,它只适用于比 MAX_PATH 短的路径(注意 Vista shell 试图软化这个限制,简要描述 以下)。这意味着如果 .NET 支持长路径,那么我们会让你 创建您无法通过资源管理器或命令访问的文件 迅速的。

    也就是说,我们意识到执行 260 个字符的限制并不是一个 合理的长期解决方案。我们的客户不会遇到这种情况 经常出现问题,但当他们这样做时,他们非常 不便。一种可能的解决方法是 P/Invoking Windows API 和使用 \?\ 前缀,但这将是大量的代码 复制 System.IO 中的功能。所以要解决 问题,客户经常求助于目录大修 组织,人为地缩短目录名称(并更新 每个参考位置)。

    http://blogs.msdn.com/b/bclteam/archive/2007/02/13/long-paths-in-net-part-1-of-3-kim-hamilton.aspx

    【讨论】:

    • +1 参考 为什么 它是这样工作的。考虑到底层文件系统都支持长路径名,即使这个推理似乎也很奇怪。
    • 我的问题是为什么 Path.GetDirectoryName(filename) 必须依赖于限制。我认为它必须只是字符串操作,因此不应依赖于限制。限制应该只在保存文件时发挥作用。在 **Path.GetFileName(fileName) 旁边完美运行**。
    【解决方案2】:

    来自MSDN documentation

    最大路径长度限制

    在 Windows API 中(下面将讨论一些例外情况 段落),路径的最大长度为 MAX_PATH,即 定义为 260 个字符。本地路径的结构如下 顺序:驱动器号、冒号、反斜杠、名称组件以分隔 反斜杠和终止空字符。例如, 驱动器 D 上的最大路径是“D:\some 256-character path string” 其中“”表示不可见的终止空字符 当前系统代码页。 (字符 在这里用于 视觉清晰,不能成为有效路径字符串的一部分。)

    【讨论】:

      【解决方案3】:

      截至撰写本文时,有 3 种解决方法可以解决 Path.GetDirectoryName 的问题,但在提出原始问题时并不存在

      1- 适用于 Windows 10 版本 1607 及更高版本

      若要在 Windows 10/Windows Server 2016 中启用对长路径的内置支持,请使用 Regedit.exe 编辑器将注册表项 HKLM\SYSTEM\CurrentControlSet\ControlFileSystem 中 REG_DWORD 的 LongPathsEnabled 参数设置为值 1

      参考https://theitbros.com/destination-path-too-long-error-when-movingcopying-a-file/

      2- 将 .NET Framework 目标版本更改为 4.6.2 或更高版本。 该版本支持长路径

      参考https://docs.microsoft.com/en-us/dotnet/api/system.io.pathtoolongexception?redirectedfrom=MSDN&view=netframework-4.6.2

      3- 对于面向 Framework 版本 4.6.1 或更早 的 .NET 应用程序,将其添加到 app.config

      <?xml version=”1.0″ encoding=”utf-8″?>
      <configuration>
      <startup>
      <supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.0″/>
      </startup>
      <runtime>
      <AppContextSwitchOverrides value=”Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false” />
      </runtime>
      </configuration>
      

      这避免了 OP 要求的 Path.GetDirectoryName 异常,但您仍然无法创建长目录。

      参考https://theitbros.com/destination-path-too-long-error-when-movingcopying-a-file/ 解决方案 7

      【讨论】:

        【解决方案4】:

        这只是应用于输入的验证,因此输出是有效路径。这在返回的路径将用于对文件系统进行进一步调用的情况下是可取的,这通常是这种情况。从技术上讲,您不需要添加此验证,但如果它有利于您最常见的场景,这是一个很好的设计。除此之外,我怀疑此方法使用通用内部代码进行路径解析,而不是仅为此方法复制解析代码。

        【讨论】:

          猜你喜欢
          • 2012-04-30
          • 2011-02-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多