为什么我不能删除在 ProgramData 中创建的目录?

Why can't I delete a directory created in ProgramData?

我正在尝试创建一个目录,然后将其删除(出于测试目的,我会省略,但如果需要可以提供详细信息)。

像这样:

>>> import os
>>> os.makedirs('C:\ProgramData\dir\test')
>>> os.remove('C:\ProgramData\dir\test')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
PermissionError: [WinError 5] Access is denied: 'C:\ProgramData\dir\test'

尽管我是 运行 作为管理员的口译员,但我总是被拒绝访问。另外我手动删除目录也没问题。

使用os.rmdir删除文件夹。 os.remove用于删除文件。

使用os.rmdir删除目录。在 Windows 上,这是通过调用 WinAPI 函数 RemoveDirectory. os.remove is implemented by calling DeleteFile, which is only meant for deleting files. If the filename argument is a directory, the call fails and it sets the last error code to ERROR_ACCESS_DENIED 实现的,Python 3 为此引发了一个 PermissionError

在这种情况下,拒绝访问错误是基于内核、系统进程、服务、环境子系统和应用程序之间的 NTSTATUS code STATUS_FILE_IS_A_DIRECTORY, i.e. RtlNtStatusToDosError(0xC00000BA) == 5. Often the kernel's status code is more informative than the corresponding WinAPI error, but not always, and there isn't always a simple mapping from one to the other, depending on the division of labor。在这种情况下,我认为内核状态代码无疑比一般的访问被拒绝错误更能提供信息。

在较低级别上,尝试通过 DeleteFile 删除目录时出错的原因是它调用系统服务 NtOpenFile with the FILE_NON_DIRECTORY_FILE flag set in OpenOptions, whereas RemoveDirectory specifies FILE_DIRECTORY_FILE. Subsequently both functions call NtSetInformationFile 来设置 FileDispositionInformation 以删除文件或目录。


作为一个逆向投资者,让我们在 NTFS 文件系统上仅使用 file 操作来实现整个序列。

>>> import os, pathlib
>>> base = pathlib.Path(os.environ['ProgramData'])

创建'dir'目录:

>>> dirp = base / 'dir::$INDEX_ALLOCATION'
>>> open(str(dirp), 'w').close()
>>> os.path.isdir(str(dirp))
True

通过手动指定流类型为$INDEX_ALLOCATION,打开这个'file'实际上创建了一个NTFS目录。顺便说一句,您还可以将多个命名的 $DATA 流添加到 目录 。请参阅 file streams 主题。

接下来创建'test'子目录并调用os.remove删除它:

>>> test = base / 'dir' / 'test::$INDEX_ALLOCATION'
>>> open(str(test), 'w').close()
>>> os.path.isdir(str(test))                       
True
>>> os.remove(str(test))
>>> os.path.exists(str(test))
False

您可能会惊讶于这有效。请记住,本例中的文件名明确指定了 $INDEX_ALLOCATION 流。这会否决 FILE_NON_DIRECTORY_FILE 标志。你得到你所要求的。但不要依赖于此,因为这些流是 NTFS 的实现细节,它不是 Windows.

上唯一使用的文件系统