【问题标题】:Delete a file instead of marking it for deletion删除文件而不是将其标记为删除
【发布时间】:2015-08-12 09:18:51
【问题描述】:

我正在为 Windows(从 XP 到 8.1)编写服务。我需要递归删除一个文件夹,为此我使用DeleteFileRemoveDirectory。 我不想使用SHFileOperation,因为它有MAX_PATH 的限制。

问题在于,有时RemoveDirectory 会以ERROR_DIR_NOT_EMPTY 失败,即使目录为空。 我发现这是因为DeleteFile 是异步工作的,它只会“标记”要删除的文件。因此,在调用RemoveDirectory 之前添加一个小延迟(睡眠)可以解决此问题。但我正在寻找一种更清洁的方法。

那么,有没有办法确保标记的文件被完好无损地删除?

我已经尝试直接在目录上调用FlushFileBuffers,但没有成功。

编辑:有些人声称NtDeleteFile 可以删除文件,即使文件上打开了句柄。我刚刚检查过它是错误的,至少在 Windows 8.1 上是错误的:只有当所有句柄都关闭时才会删除文件。

【问题讨论】:

  • ...the file deletion does not occur until the last handle to the file is closed 看起来有人正在使用 FILE_SHARE_DELETE 打开文件,而您添加的睡眠恰好在最后一个 CloseHandle 之后移动了 RemoveDirectory 调用。你能识别开瓶器并确定它是否在你的控制之下吗?如果是,您必须使其与删除过程配合。不知道,您将如何防止不相关的进程通过保持打开的文件来拒绝您删除目录:S
  • 唯一现实的解决方案是在短暂延迟后重试。您可能会发现几毫秒就足够了。

标签: c++ c file winapi


【解决方案1】:

我不想使用 SHFileOperation,因为它有 MAX_PATH 限制。

在 Vista+ 上,您可以(并且应该)使用 IFileOperation 而不是 SHFileOperation()。那么你就不受任何路径长度的限制了,它可以在服务中安全使用,不像SHFileOperation()

Is it wrong to call SHFileOperation from a service?

Is it wrong to call SHFileOperation from a service? Revised

So you decided to call SHFileOperation from a service, at least remember to disable copy hooks

那么,有没有办法确保标记的文件被完好无损地删除?

不是真的。这些文件或者正在使用中,或者没有从缓存管理器中清除,等等。 If DeleteFile() 成功,您知道文件将被删除最终。您只需给系统时间实际上删除它。如果您收到ERROR_DIR_NOT_EMPTY,请等待几秒钟,然后重试。如果您在多次尝试后仍然收到ERROR_DIR_NOT_EMPTY,则您的操作失败,因为该文件夹显然还没有准备好被删除,或者只是继续尝试直到它最终成功,定期枚举文件(以防创建新文件)。

【讨论】:

  • IFileOperation 将删除与 XP 的兼容性...当然,我可以等待,以防得到 ERROR_DIR_NOT_EMPTY,但我想做的是在系统关闭时同步数据,所以一切都必须尽可能快。这也是为什么我无法使用 rd 命令可靠地启动诸如 cmd.exe 之类的进程的原因。也就是说,我只是做了一些进一步的测试,似乎罪魁祸首是资源管理器:通过关闭资源管理器的所有窗口,问题不再出现。但这并没有真正帮助我,因为可能还有其他进程可以做类似的事情。
  • 如果这是在系统关闭期间,您真的不能等待太久。即使您使用ShutdownBlockReasonCreate()(也仅限Vista+)在您等待时阻止关机,用户也可以覆盖您并告诉Windows 强制终止您的应用程序。仅在 XP 上,您几乎可以无限期地阻止关机。但是是的,无论哪种方式,Explorer 都有一个习惯,即在显示文件夹/文件时保持它们处于打开状态。
  • @v77 为什么不用MoveFileExMOVEFILE_DELAY_UNTIL_REBOOT 延迟删除直到重新启动?另外,您应该在问题中提出有关关机的内容,这对我来说听起来像是相关信息
  • @Remy:在 Vista+ 上,有 SERVICE_CONTROL_PRESHUTDOWN 通知,它可以提供尽可能多的时间。但是如果有大量文件夹无法立即删除,这将花费大量时间,并且关闭,这是不可接受的。
  • @v77:更有理由将删除延迟到下一次系统启动,就像 Diego 建议的那样。
猜你喜欢
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 2013-04-09
  • 2020-05-30
  • 2014-11-25
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多