如何获取与打开的句柄关联的名称
在Win32中获取与打开的HANDLE相关联的文件名的最简单方法是什么?
解决方案
回答
在Unix上,没有可靠的方法可以做到这一点。在具有传统unix文件系统的unix中,我们可以打开一个文件,然后取消链接(从目录中删除其条目)并使用它,此时该名称不会存储在任何地方。另外,由于一个文件可能有多个进入文件系统的硬链接,所以每个名称都是等效的,因此一旦有了打开的句柄,就不清楚应该将其映射回哪个文件名。
因此,我们也许可以使用其他答案在Win32上执行此操作,但是如果我们需要将应用程序移植到Unix环境中,那将会很不幸。我的建议是,如果可能的话,请重构程序,这样我们就不需要操作系统就能保持开放的资源到文件名的连接。
回答
编辑感谢我们对此的评论,仅适用于Vista或者Server 2008. 我在页面上错过了。猜猜我应该阅读整篇文章;)
看起来我们可以使用GetFileInformationByHandleEx()来获取此信息。
我们可能会想要执行以下操作:
GetFileInformationByHandleEx( fileHandle, FILE_NAME_INFO, lpFileInformation, sizeof(FILE_NAME_INFO));
仔细检查MSDN页面,以确保我没有严重误导你:)
干杯,
泰勒
回答
如果我们需要在Win32 Vista或者Server 2008上执行此操作,请查看GetMappedFileName(...)函数,该函数是Win32中保密程度最高的秘密之一。加上一点C / C ++-fu,我们可以在内存中映射所讨论文件的一小部分,然后将该句柄传递给此函数。
另外,在Win32上,我们不能真正删除打开的文件(另一个答案中提到的打开/取消链接问题),可以将其标记为关闭时删除,但它仍会徘徊,直到其最后一个打开句柄关闭。 Dunno如果在这种情况下通过文件mmap(...)映射文件会有所帮助,因为它必须指向物理文件...
-=詹姆斯。
回答
FWIW,这是Prakash在Python中使用奇妙的ctypes建议的MSDN文章中的相同解决方案:
from ctypes import * # get handle to c:\boot.ini to test handle = windll.kernel32.CreateFileA("c:\boot.ini", 0x80000000, 3, 0, 3, 0x80, 0) hfilemap = windll.kernel32.CreateFileMappingA(handle, 0, 2, 0, 1, 0) pmem = windll.kernel32.MapViewOfFile(hfilemap, 4, 0, 0, 1) name = create_string_buffer(1024) windll.psapi.GetMappedFileNameA(windll.kernel32.GetCurrentProcess(), pmem, name, 1024) print "The name for the handle 0x%08x is %s" % (handle, name.value) # convert device name to drive letter buf = create_string_buffer(512) size = windll.kernel32.GetLogicalDriveStringsA(511, buf) names = buf.raw[0:size-1].split("##代码##") for drive in names: windll.kernel32.QueryDosDeviceA(drive[0:2], buf, 512) if name.value.startswith(buf.value): print "%s%s" % (drive[0:2], name.value[len(buf.value):]) break