使用ReadDirectoryChangesW监视文件夹会导致其父文件夹被锁定并且无法删除。
这里有关于此的帖子:
FindFirstChangeNotification locks parent folder
但是其中提到的唯一解决方案是,我们应该始终在顶层进行聆听。
有没有人找到一种更好的方法来代替顶级的观看呢?
有时候这可以一直到观看云端硬盘,并且在计算机上不会花费很多处理时间。
谢谢!
答案 0 :(得分:1)
文件夹只有在为空的情况下才能被删除,否则我们将收到错误STATUS_DIRECTORY_NOT_EMPTY
-表示尝试删除的目录不为空。
从另一面看-如果您有打开文件的句柄-除非将其关闭,否则不能将其删除(此处的某些更改从win10 rs1 开始)
因此,如果您用ReadDirectoryChangesW
监视某些子文件夹,则您已打开了该文件的句柄,并且在不关闭该句柄之前,不能删除父文件(在WIN10_RS1 之前)。 / p>
通常的过程是-当有人尝试删除文件夹时-它必须枚举其中的所有文件(子文件夹)并首先将其删除。当将删除操作应用于调用了ReadDirectoryChangesW
的文件夹时-io请求将以状态STATUS_DELETE_PENDING
完成-已请求对未删除的文件对象执行非关闭操作。 (它转换为win32错误代码ERROR_ACCESS_DENIED
-访问被拒绝。)。当您从ReadDirectoryChangesW
收到此错误时,必须关闭此调用中使用的目录句柄。然后是加薪-首先是谁-您关闭目录句柄或其他代码尝试删除父文件夹...
从win10 rs1开始可能删除父文件,即使有人通过用NtSetInformationFile
调用FileDispositionInformationEx
或用SetFileInformationByHandle
调用FileDispositionInfoEx
对其子文件(文件夹)保持打开句柄。
新标记FILE_DISPOSITION_POSIX_SEMANTICS
中的魔术(指定系统应执行POSIX风格的删除)
通常,直到所有 文件的打开句柄已关闭,并且链接计数 文件为零。将文件标记为删除时
FILE_DISPOSITION_POSIX_SEMANTICS
,该链接将从 POSIX删除句柄关闭后立即可见的名称空间, 但是文件的数据流仍然可以被其他现有用户访问 直到最后一个手柄已关闭。
因此,当我们使用此选项时-当然,文件本身不会被删除,直到ReadDirectoryChangesW
的调用者不会关闭自身句柄,但是文件将从父文件夹中删除。结果父文件夹可以变成空,然后我们可以将其删除。
请注意,此处的DeleteFileW
和RemoveDirectoryW
在这里不起作用,因为它们将旧的信息类FileDispositionInformation与FILE_DISPOSITION_INFORMATION
一起使用
ULONG DeletePosix(PCWSTR lpFileName)
{
HANDLE hFile = CreateFileW(lpFileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
static FILE_DISPOSITION_INFO_EX fdi = { FILE_DISPOSITION_DELETE| FILE_DISPOSITION_POSIX_SEMANTICS };
ULONG dwError = SetFileInformationByHandle(hFile, FileDispositionInfoEx, &fdi, sizeof(fdi))
? NOERROR : GetLastError();
// win10 rs1: file removed from parent folder here
CloseHandle(hFile);
return dwError;
}
当然,子级必须在其他调用中以FILE_SHARE_DELETE
打开,否则我们以后根本无法通过DELETE
访问来打开它
答案 1 :(得分:0)
获取目录句柄时,为CreateFile()
指定正确的属性很重要。试试这个:
HANDLE hDir = ::CreateFile(
strDirectoryName,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, // security descriptor
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
对于共享模式,也必须指定FILE_SHARE_DELETE
。