背景

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

问题

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

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

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

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

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

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

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

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

有帮助吗?

解决方案

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

其他提示

我跑成一个第三方的解决方案,可以帮助: AlphaFS

应该很容易解决这个限制有位平台调用的,假设你的软件有必要的权限:

[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
    }
}

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

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

理想情况下你映射远尽可能的路径。

我不得不使用下面的小脚本成功删除的目录结构。 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top