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

时间:2015-04-22 12:45:36

标签: c++ windows winapi smb

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

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

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

所以我的主要问题是:FindFirstFile / FindNextFile“看到”CopyFile_access都看不到的网络文件夹上的文件怎么可能?< / p>

其他信息/诊断:

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

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

1 个答案:

答案 0 :(得分:7)

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

有关详细信息和计划性工作,请参阅this blog文章。

它声明:

  

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

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

  

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

     

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

     

下      

HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \服务\ LanmanWorkstation \参数:

     

FileInfoCacheLifetime

     

FileNotFoundCacheLifetime

     

DirectoryCacheLifetime

     

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

     

程序化解决方法?

     

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

     

使用FindFirstChangeNotification Function(Windows)API进行注册   变化。