我不知道你想找哪两个:给定的文件是否有任何现有的句柄,如handle和Process Explorer工具所示?在
对于给定的文件,是否存在任何现有的锁定句柄,如Unlocker工具所示。在
但不管怎样,答案都是相似的。在
显然这是可行的,还是那些工具做不到,对吧?不幸的是,Python stdlib中没有任何东西可以帮助您。那么,你是怎么做到的?在
您需要通过^{}、ctypes或其他方式访问Windows api函数。在
有两种方法。第一种,处理NT内核对象api要困难得多,只有在需要使用非常旧版本的Windows时才需要。第二个,^{},可能是你想要的。在
细节相当复杂(而且没有很好的文档记录),但是它们被解释为in a CodeProject sample program和{a7}。在
如果您不了解这些页面上的代码,或者不了解如何从Python调用它,那么您就不应该这样做。如果你明白了要点,但是有问题,或者陷入困境,你当然可以在这里(或者在sysinternals论坛或其他地方)寻求帮助。在
但是,即使您以前已将ctypes用于Windows,也有一些您可能不知道的注意事项:
其中许多函数要么没有文档化,要么文档没有告诉您在哪个DLL中找到它们。它们都将位于ntdll或kernel32;但是,在某些情况下,文档中的{}名称只是实际ZwFooBar函数的别名,因此,如果在两个DLL中都找不到NtFooBar,请查找ZwFooBar。在
至少在旧版本的Windows上,ZwQuerySystemInformation的行为与预期不符:不能用0SystemInformationLength调用它,请检查ReturnLength,分配一个该大小的缓冲区,然后再试一次。你唯一能做的就是从一个有足够空间的缓冲区开始,比如说,8个句柄,试试看你是否得到了一个错误状态“信息”长度“不匹配”,增加这个数字8,然后再试一次,直到成功(或者由于另一个错误而失败)。代码如下所示(假设您定义了SYSTEM_HANDLE结构):STATUS_INFO_LENGTH_MISMATCH = 0xc0000004
i = 8
while True:
class SYSTEM_HANDLE_INFORMATION(Structure):
_fields_ = [('HandleCount', c_ulong),
('Handles', SYSTEM_HANDLE * i)]
buf = SYSTEM_HANDLE_INFORMATION()
return_length = sizeof(buf)
rc = ntdll.ZwQuerySystemInformation(SystemHandleInformation,
buf, sizeof(buf),
byref(return_length))
if rc == STATUS_INFO_LENGTH_MISMATCH:
i += 8
continue
elif rc == 0:
return buf.Handles[:buf.HandleCount]
else:
raise SomeKindOfError(rc)
最后,文档并没有真正解释这一点,但是从您知道的句柄(即文件)到路径名的方法有点复杂。只要使用NtQueryObject(ObjectNameInformation)就可以返回一个内核对象空间路径名,然后必须将其映射到DOS路径名、可能是UNC普通NT路径名或\?\路径名。当然,第一种方法不适用于没有映射驱动器号的网络驱动器上的文件;前两种方法都不适用于路径名很长的文件。在
当然还有一个更简单的选择:只需通过handle、Unlocker或其他一些命令行工具。在
或者,在这两者之间,构建上面链接的CodeProject项目,通过ctypes打开它的DLL并调用它的GetOpenedFiles方法,它将为您完成艰苦的工作。在
由于该项目构建了一个普通的WinDLL样式DLL,因此可以用普通的ctypes方式调用它。如果您从未使用过ctypes,那么文档中的示例将向您展示您需要了解的几乎所有内容,但我将提供一些伪代码以帮助您开始使用。在
首先,我们需要为要编写的回调函数创建一个OF_CALLBACK类型,如Callback functions中所述。由于OF_CALLBACK的原型是在一个.h文件中定义的,我无法到达这里,所以我只是猜测一下;您必须查看真实版本并自己翻译它。但是你的代码应该是这样的:
^{pr2}$
很有可能你在回调中得到的实际上是一个指向某种结构或结构列表的指针,你必须定义与直接调用Nt/Zw函数相同的SYSTEM_HANDLE,所以让我来举个例子,如果你在回调中返回一个SYSTEM_HANDLE *,而不是HANDLE,就这么简单:
^{公关3}$