Long Paths in .NET, Part 1 of 3 [Kim Hamilton][译]

[一猪: 第一次翻译, 希望看到的人多看原文和评论, thanks.]

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


让我们从BCL中的一个有趣的异常开始今天的话题:

[PathTooLongException]: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

我们的客户在bug报告里说: “路径最多只有260个字符? MS搞笑的吧. 把这个限制搞得更长一些!”. 在这里我将会对这些提交bug报告的人(很抱歉你们的bug被关成了”won’t fix”)详细解释这个问题并告诉你们我们对此所作出的努力.

让我们先来澄清一些术语:

  • Path: 一个文件的全路径. 比如你又一个文件: c:\temp\fileA.txt, 那么通常你会叫这个文件fileA.txt, 但它的全路径应该是c:\temp\fileA.txt.
  • MAX_PATH: Windows API定义的路径的最大长度, 260个字符.
  • Long path: 一个长度超过了MAX_PATH的路径.
  • Long file name: long path还不一样. 这个其实是用来跟短文件名作对比的, 就是以前我们说的那个8.3格式的文件名.

众所周知.NET API是依赖于Windows API, 从这一点上看, 上面的这个异常就没有什么问题了. 然而Windows API还提供了一个方法来绕过这个MAX_PATH的限制. 如果你在你的文件路径前面加上”\\?\”的前缀, 然后调用unicode版本的Windows API, 那么你的path的最大长度就可以达到32k. 也就是说你只要加上前缀”\\?\”就可以在Windows API中使用long path.

没有人会抱怨32k的长度限制了, 那么是不是就可以说问题解决了呢? 也不完全是. 过去我们不愿意支持long path是有原因的, 而且现在我们还会考虑这些原因.

第一个原因就是安全. 前缀”\\?\”并不仅仅是打破的long path的限制, 它还能让path在到达文件系统之前只受到Windows API的最小的修正. 这样做的结果就是”\\?\”规避了Windows API对于path的一系列的标准化的操作: 去掉path后面的空格, ’.’’..’扩展为相应的内容, 以及把相对路径转换成全路径等等. .Net中的如果用FileIOPermission attribute来保证安全, 我们就不得不使用标准化后的路径. 而不用FileIOPermission就会有安全隐患. 现在我们明白了如果我们用前缀”\\?\”来解决long path的问题的话, 我们就必须能像Windows API那样把路径标准化.

第二个原因是支持long path可能导致的不一致行为. 很多操作文件的Windows API都支持以”\\?\” 作为前缀的long path, 但仅仅是很多而不是全部. 比如LoadLibrary, 它的功能是将一个module映射到调用者的地址空间, 在文件路径超过MAX_PATH的时候就会失败. 这就意味着你可以调用MoveFile把一个DLL放到一个路径长度超过MAX_PATH的地方, 但是当你想加载这个DLL的时候却失败了. Windows API里面有很多这样的例子, 虽然有一些权宜之计, 但都是针对特殊问题的, 没有一个通用的解决方案.

另外一个因素, 也是最痛苦的一个, Windows ApplicationWindows shell本身在long path上的兼容性. 因为Windows shell本身只支持长度小于260的路径 (下面会讲到Vista shell弱化了这个限制). 就是说如果.NET支持了long path, 那么你就可以通过你的.NET App创建一些在Explorer或是命令行中不能访问的文件了. J

我们已经意识到了260个字符的限制并不是很合理. 我们的客户并不经常碰到这个问题, 但是一旦需要一个超出MAX_PATH的路径, 就会觉得很不方便. 一个权宜之计是P/Invoking Windows API并使用\\?\前缀, 但是这样就不得不写一大坨跟System.IO重复的code. 所以为了解决这个问题, 我们的客户常常会重新设计目录结构, 绞尽脑汁的缩短目录名.

因为这个问题已经逐渐变得普遍, 所以无论是.NET framework还是别的领域, MS都已经开始着手解决这个问题. 实际上在vista中你应该已经可以看到我们为了减少出现MAX_PATH的问题的几率所作出的改动: 很多特定的目录名已经被缩短 (译注: \Documents and Settings à \Users, 实际上, MS有一个专门的aliaslongpath来谈论这个问题), shell还有一个auto-path shrinking的功能, 它会用比较短的别名来表示路径以把那些long path压缩在260个字符以内.

这是我写的关于long pathblog这一系列的第一篇. 在后面的篇幅中我们会讲到在CLR的未来版本中让System.IO支持long path的计划, 并告诉你几个临时的解决方案.

相关的连接:

MSDN上关于命名规则, 长度和\\?\前缀的文档:
http://msdn2.microsoft.com/en-us/library/aa365247.aspx

Michael Kaplanblog会告诉你Vista的改变:
http://blogs.msdn.com/michkap/archive/2006/12/13/1275292.aspx

posted @ 2007-04-26 13:54 光阴四溅 阅读(...) 评论(...) 编辑 收藏