c++ - 为什么 FindFirstFile/FindNextFile 有时会看到网络文件夹中的文件,而 CopyFile 却看不到?

标签 c++ windows winapi smb

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

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

我觉得这难以置信,所以我给 _access 添加了一个电话到检查文件是否存在的备份功能 CopyFile叫做。结果与 CopyFile 相同,即 _access报告文件不存在(返回代码 -1 且 errno 为 2,即 ENOENT )。

所以我的主要问题是:FindFirstFile 怎么可能/FindNextFile “看到”网络文件夹上的文件既不 CopyFile也不_access能看到吗?

附加信息/诊断:

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

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

最佳答案

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

参见 this blog archive 文章了解更多信息和程序化解决方法。

File.Exists /_access / GetFileAttributes / FindFirstFile,FindNextFile / _stat behavior over SMB 2.0

What is really happening?

This is because of the local caching included on the client side with SMB 2.0. When the SMB 2.0 session has been created, the local cache will be available on the client side, which will be refreshed after every 10 seconds by default. Any further request to the file exists will be checked against this local cache rather than going to the server share. So, if a local cache is built on client, and on server share a new file is created, local cache has not been invalidated and not in sync with server share, any further request for checking the new file existence will fail.

This is root cause, but by design. If the local cache is updated and in sync with server share, request will be successful.

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

How do I control the local cache lifetime?

You can create registry keys below to control the cache lifetime.
Under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters:

  • FileInfoCacheLifetime
  • FileNotFoundCacheLifetime
  • DirectoryCacheLifetime

They are all REG_DWORD type in seconds.

Programmatic workaround?

Register for directory or file change notifications using Win32 API.
Use FindFirstChangeNotification Function (Windows) API to register for changes.

关于c++ - 为什么 FindFirstFile/FindNextFile 有时会看到网络文件夹中的文件,而 CopyFile 却看不到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29798025/

相关文章:

javascript - 使用 ActiveX DeleteFile 时权限被拒绝

c++ - 如何实例化 std::exception_ptr 以进行单元测试

c++ - 在 vs2010 上构建 opengl 项目后出现一些错误

windows - 如何在 Visual Studio 中嵌入命令 shell

winapi - Windows 8 ARM是否也称为 "Windows RT"是否有第三方开发人员可以使用Winapi(win32)?

windows - Windows 路径上的前导 "\??\"是什么意思?

c++ - 从应用程序中使用提升的权限调用 win32 服务中的方法

c++ - OpenMP 任务等待不工作

c++ - priority_queue - 删除不在顶部的元素

windows - 在我的系统上找不到 Monodevelop 的 mdtool