【发布时间】:2017-04-24 01:47:08
【问题描述】:
虽然文档含糊不清,但基于 this question and comments 和 this answer,我预计使用第三个参数(备份文件名)调用的 ReplaceFile 应该成功,即使在其他进程中打开了源文件和目标文件的句柄没有FILE_SHARE_DELETE 标志。应该通过仅更改不受锁控制的文件元数据(=目录条目)来克服锁。 (所有三个文件都在同一个磁盘驱动器上,因此更改元数据足以重命名它们。)
但是,下面的代码因ERROR_SHARING_VIOLATION 而失败。这不是我的用例,而只是失败的演示。用例是我试图重命名在系统上的其他进程中偶尔(并且不可预测地)打开的文件,例如防病毒或备份程序,这些文件没有使用FILE_SHARE_DELETE 标志。
# python 3
import os
import ctypes
fname1 = 'test1.txt'
fname2 = 'test2.txt'
f1 = open(fname1, 'w')
f1.write(fname1)
f2 = open(fname2, 'w')
f2.write(fname2)
# tmp123 does not exist when the program is started
ctypes.windll.kernel32.ReplaceFileW(fname2, fname1, 'tmp123', 0, None, None) # 0
ctypes.GetLastError() # ERROR_SHARING_VIOLATION
# if we close file handles, it works as expected
f1.close()
f2.close()
ctypes.windll.kernel32.ReplaceFileW(fname2, fname1, 'tmp123', 0, None, None) # 1
为什么?
【问题讨论】:
-
如果文件在另一个应用程序中打开,您可能无法删除文件,原因与此相同。写完后,如果你完成了,你应该总是关闭文件。我认为这在大多数语言中都很常见。您打开一个文件,除非您关闭对它的第一个引用,否则您无法再次打开它以获得 R/W/A priv。
-
@Fallenreaper 我编辑了问题以澄清我想要做什么。我不会对结果感到惊讶,除了我在问题中链接的帖子非常清楚地表明它应该可以正常工作。
-
啊,我会刷新并阅读您的文档。
-
您的一篇帖子说这个问题很难解决,因为它天生就内置在 Windows 中,即针对文件的竞争条件的想法。另一个说重命名不会删除文件,也不应该抛出错误。由于这是一个共享错误,这会让我相信即使重命名它也会导致问题,因为另一个进程仍然打开它。一种选择可能是启动某种子进程,当进程完成它们正在做的任何事情时,它会进行替换。如果需要继续,则必须设置等待,或查找并杀死进程
-
ReplaceFile失败,因为它尝试使用DELETE访问掩码打开 lpReplacedFileName。但这会给出错误ERROR_SHARING_VIOLATION如果文件已经打开而没有FILE_SHARE_DELETE
标签: python winapi window filesystems