【问题标题】:How to rename a file without closing all of it's open file handles?如何在不关闭所有打开的文件句柄的情况下重命名文件?
【发布时间】:2018-03-05 10:00:08
【问题描述】:

我用createFile 创建GENERIC_READ 文件句柄。 这是我的指示:

   hfile :=  CreateFileA(aFileName,  
                         GENERIC_READ,  
                         FILE_SHARE_READ or 
                           FILE_SHARE_WRITE,  
                         nil,  
                         OPEN_EXISTING,  
                         FILE_ATTRIBUTE_NORMAL or 
                           FILE_FLAG_SEQUENTIAL_SCAN or 
                             FILE_FLAG_OVERLAPPED, 
                         0);  

现在的问题是,何时进程将通过hfile 读取文件,有时另一个进程需要“交换”文件,为此需要重命名它

这就是我的做法:

MoveFileA(aFileName, aNewFileName);

但是当我这样做时他们仍然有一些文件句柄打开时我有一个错误。他们有什么方法可以在不先关闭所有 GENERIC_READ 文件句柄的情况下重命名文件吗?

【问题讨论】:

  • := - 你又在编程什么?
  • @StoryTeller Delphi 和 C++(这里的代码示例来自 delphi)
  • 这似乎是一个德尔福赋值运算符。
  • 是的,当我进一步阅读并看到nil 时,我很明智。那么,我对您问题中的 C++ 标记感到矛盾。它不是 C++ 特定的,是吗?甚至不是特定于 Delphi,但至少代码是 Delphi。
  • MoveFile 通过NtOpenFile 打开句柄并通过NtSetInformationFile 进行重命名。重命名文件本质上是从其当前目录中删除,因此它需要删除访问权限,这是一种共享访问权限(请参阅IoCheckShareAccess)。在文件系统的文件/流控制块中有一个 SHARE_ACCESS 记录,供所有引用 FCB/SCB 的内核文件对象使用。

标签: windows winapi file-io createfile


【解决方案1】:

显然首选是确保每次打开文件时都传递FILE_SHARE_DELETE 标志。

如果您不能这样做(例如,您无法控制的某些其他进程可能会打开它),剩下的替代方法是使用 MoveFileExMOVEFILE_DELAY_UNTIL_REBOOT 标志。正如您从名称中猜到的那样,这会等到下次重新启动计算机时,然后重命名它。这对于由诸如服务之类的东西使用的文件特别有用,该服务会在服务启动时立即打开它们,并保持它们打开直到系统关闭。

这确实有它自己的一些限制。例如,您不能使用它通过网络共享重命名文件。重命名在启动过程的早期相当完成,在重新连接持久网络共享之前。

【讨论】:

    【解决方案2】:

    在文件中打开另一个HANDLE,然后使用SetFileInformationByHandle(),将FileInformationClass 参数设置为FileRenameInfo,并将lpFileInformation 参数设置为指向FILE_RENAME_INFO 结构的指针。

    【讨论】:

    • MoveFile[Ex] 基本上以相同的方式工作,只是它直接使用 NTAPI NtOpenFileNtSetInformationFile 而不是 WINAPI CreateFileSetFileInformationByHandle。重要的是,MoveFile 也直接打开了一个重解析点。仅当重新解析点不是挂载点(连接点)或符号链接时,它才会重新打开并重新解析。
    【解决方案3】:

    只需添加 FILE_SHARE_DELETE 即可完成工作

    【讨论】:

    • 不是我的反对意见,但如果你用上下文充实答案以表明你真正理解它是如何工作的,这可能会有所帮助。它假设所有需要数据访问(即执行、读取、写入、追加或删除)的用户都进行合作。只需要元数据访问(即读写 [扩展] 属性;所有者/组;以及自主和系统 ACL)的用户不需要合作。由于您只有读取访问权限并共享所有访问权限,因此后续打开具有读取、写入或删除访问权限仅需要至少共享读取访问权限。
    猜你喜欢
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 2021-05-26
    • 2010-11-04
    相关资源
    最近更新 更多