为什么FindFirstFile/FindNextFile有时会在网络文件夹中看到一个文件,但CopyFile却没有?

her*_*ube 4 c++ windows smb winapi

我有一个函数应该通过将所有文件从源文件复制到目标文件夹来创建源文件夹的备份.该函数使用由FindFirstFile/ 驱动的while循环FindNextFile,然后调用函数CopyFile找到的每个文件Find....

现在,当源文件夹是SMB网络路径时(无论我是使用映射驱动器还是UNC路径),有时会FindNextFile"看到"文件,但CopyFile拒绝复制文件.错误代码是2,即ERROR_FILE_NOT_FOUND.

我发现这很难相信,所以我添加了一个调用_access备份函数,该函数在CopyFile调用之前检查文件是否存在.结果与for相同CopyFile,即_access报告文件不存在(返回代码-1并且errno为2,即ENOENT).

所以我的主要问题是:如何FindFirstFile/ FindNextFile"看到"网络文件夹中既CopyFile没有_access也看不到的文件?

附加信息/诊断:

  • 有问题的文件是在备份功能运行之前立即创建的文件.具体来说,它的工作原理如下:在客户端计算机上运行的进程与在服务器计算机上运行的进程具有网络连接.客户端进程告诉服务器进程创建该文件.这应该是同步工作的:只有在服务器进程确认已创建文件之后,客户端进程才会继续执行备份.
  • 我在备份功能中添加了重试机制.有了这个,CopyFile_access在重试约4秒后突然开始看到有问题的文件.这向我表明确实存在某种网络延迟.因为如果它出现FindFirstFile/ FindNextFile不同接入网络的路径比CopyFile/ _access.

不幸的是,我对这种效果的研究没有发现任何有用的信息,所以我只能推测.如果FindFirstFile/ FindNextFile/ CopyFile确实不能很好地协同工作,你知道一组不同的查找/复制API函数吗?

Mik*_*ine 7

这可能是因为Windows上的SMB 2.0维护的缓存只能每10秒刷新一次.

有关更多信息和程序化工作,请参阅此博客文章.

它指出:

这是因为SMB 2.0包含在客户端的本地缓存.创建SMB 2.0会话后,客户端将提供本地缓存,默认情况下每10秒后刷新一次.对存在的文件的任何进一步请求将针对此本地缓存进行检查,而不是转到服务器共享.因此,如果在客户端上构建本地缓存,并且在服务器共享上创建新文件,则本地缓存未被无效且与服务器共享不同步,则检查新文件存在的任何进一步请求将失败.这是根本原因,但是设计.如果本地缓存已更新并与服务器共享同步,则请求将成功.

对于解决方案/解决方案,链接文章提到:

如何控制本地缓存生命周期?

您可以在下面创建注册表项以控制缓存生存期.

HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \服务\ LanmanWorkstation \参数:

FileInfoCacheLifetime

FileNotFoundCacheLifetime

DirectoryCacheLifetime

它们都是REG_DWORD类型,以秒为单位.

程序化的解决方法?

使用Win32 API注册目录或文件更改通知.

使用FindFirstChangeNotification Function(Windows)API注册更改.