如何获取与打开的句柄关联的名称

时间:2020-03-05 18:54:08  来源:igfitidea点击:

在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