9

背景

我需要使用最高版本的 .NET 2.0 编写一个工具(出于政治、商业和机密性/信任的原因,此客户端不能使用现成的东西)通过网络将文件从一台服务器迁移到另一台服务器。服务器是本地团队的文件服务器,某些团队文件夹需要迁移到其他服务器以方便重组。基本思想是我们读取每个文件并在数小时内通过网络将其流式传输,几天后数据将被迁移。需要保留文件权限。由于这将需要几天时间(对于某些团队,我们正在讨论数 GB 的数据),我们需要每晚迭代文件并比较修改日期并更新已更改的文件。理论上,最终新服务器将拥有文件的最新副本,并且用户可以切换到新服务器。当然不是这么简单,但我们有一个我们认为应该可行的设计:)

问题

所以理论上我们只是打开文件,通过网络流式传输,然后在另一端写入,对吗?:)

不幸的是,在服务器本身上,文件共享是在文件夹路径中创建的,例如:

D:\Data\Team Shares\DIVISION\DEPARTMENT\团队名称 - 可能相当长\

对于每个用户,此路径都映射到一个驱动器,例如,它将作为 \\SERVER\TEAMNAME 共享并映射到 T: 驱动器。

这导致了从 T: 驱动器可见的文件在MAX_PATH限制范围内的情况,但是当在服务器本身上本地查看时,它们远远超出了限制。我们无法使用网络共享访问文件,因为该工具需要通用,才能在数百个这样的服务器上运行,并且没有标准的方法来判断哪些文件共享是我们应该移动的,哪些不是 - 有甚至没有命名约定标准。另外,偶尔会有其他股份的子股份,所以我们MAX_PATH两次超过限额!

我知道使用“\\?\”前缀指定路径的解决方法,它将路径视为 UNC 路径并允许理论上最多 32k 个字符。

此解决方法是在 Win32 API 级别实现的,System.IO 命名空间(大部分)基本上只是原生 Win32 API 函数的薄包装,但是微软在将调用交给 API 之前“有用地”实现了额外的(不正确的)验证. 在这种情况下,.NET Framework 拒绝该路径,因为它声称“?” 是无效的路径字符。

所以我的问题是......有没有一种我没有想到的方法可以让我解决这个问题,而不必完全重写几乎整个 System.IO 命名空间,进行大量 P/Invoke 调用,只是为了删除这个烦人的验证?

4

5 回答 5

5

BCL 团队制作了一个由 3 部分组成的系列,详细说明了做出这些选择的原因以及解决方法。如果您还没有阅读,我建议您阅读,因为它是有关该主题的重要信息来源

于 2009-07-27T21:12:14.523 回答
4

我遇到了一个可能有帮助的第三方解决方案:AlphaFS

于 2009-08-25T23:34:10.030 回答
1

假设您的软件具有必要的权限,通过一些平台调用来解决此限制应该相当容易:

[DllImport("kernel32.dll", SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
  uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
  uint dwFlagsAndAttributes, IntPtr hTemplateFile);

// Must close/dispose handle separately from FileStream since it's not owned by
// that object when passed to constructor.
using (SafeFileHandle h = CreateFile(longUncPath, GENERIC_WRITE, 0, IntPtr.Zero, 
       OPEN_EXISTING, 0, IntPtr.Zero))
{
    using (var fs = new FileStream(h, FileAccess.Read))
    {
        // operations with FileStream object
    }
}
于 2009-07-27T21:17:12.377 回答
0

您可以尝试通过使用 subst.exe(或其内部使用的任何 API)映射父目录来缩短路径:

http://www.makeuseof.com/tag/how-to-map-a-local-windows-folder-to-a-drive-letter/

理想情况下,您会尽可能多地绘制路径。

于 2011-10-26T00:59:49.860 回答
-1

我已经使用下面的小脚本成功删除了目录结构。pushd 使用 UNC 格式,它为您提供 32K 而不是 260 的限制

set "folder=\\SERVER\SHARE\DIVISION\DEPARTMENT\NAME OF TEAM - COULD BE FAIRLY LONG\" 
pushd "%folder%"
for /d %%i in ("*") do rmdir "%%i" /s /q
popd
于 2015-09-16T17:21:00.273 回答