Windows 6(Vista和Server 2008)支持正确的符号链接,可以通过CreateSymbolicLink函数创建符号链接,但似乎没有相应的函数来查询符号链接以获取链接目标的路径。
我发现符号链接是重解析点的一种实现,因此重解析点函数可以用来获取目标路径。但是我需要使用重解析点的头文件似乎是Windows Driver Kit附带的。用VS 2008设置这个工具包似乎是一项不简单的任务。
是否有一个很好的简单函数,我已经错过了获得链接的目标,或者我真的必须建立一个windows驱动程序开发环境,只是为了编写代码来访问这些信息?
编辑:AdamMitz提出了GetFinalPathNameByHandle的建议,这个函数对于本地符号链接非常有效,但是对于解析远程链接(通过UNC路径)似乎不起作用。
编辑2:应亚当的要求,以下是我所尝试的更多细节:
我最初是沿着FSCTL_GET_REPARSE_POINT
/DeviceIoControl
路线走的,但那产生了REPARSE_DATA_BUFFER
结构。定义这个结构的头文件似乎只存在于Windows驱动程序工具包中。
当链接存在于本地磁盘(C:\...\link
等)上时,GetFinalPathNameByHandle()
可以正常工作。奇怪的是,我发现无论是否指定了FILE_FLAG_OPEN_REPARSE_POINT
标志,无论目标文件是否存在,都可以使用CreateFileW()
获得链接的句柄,从而获得目标文件。
当使用CreateFileW()
和GetFinalPathNameByHandle()
询问远程链路时(\\?\UNC\....
),事情开始变得复杂。如果指定了FILE_FLAG_OPEN_REPARSE_POINT
,GetFinalPathNameByHandle()
总是返回链接路径,而不是目标路径。如果没有指定FILE_FLAG_OPEN_REPARSE_POINT
,则返回目标路径。但前提是目标存在并且与链接位于同一台计算机上。如果链接指向另一台计算机,则会出现网络权限错误。如果链接指向本地不存在的文件,则会出现找不到文件错误。
2条答案
按热度按时间vcirk6k61#
符号链接既可以是绝对链接,也可以是相对链接,如果它们引用的文件具有多个路径(hardlinks),另一个答案中提到的
GetFinalPathNameByHandle
函数一般会给予你错误的答案,如果你打开符号链接本身,你只会得到符号链接本身的路径,如果你打开符号链接指向的路径,即使符号链接指向一个不同的硬链接,你也只能得到该文件的路径之一,如果该文件不存在,你甚至根本不能使用该函数。正确的答案似乎是使用C++17的
std::filesystem::read_symlink
函数,它实际上会读取重解析点数据,并给你符号链接包含的确切路径,无论是绝对还是相对,甚至在目标路径不存在的情况下也能工作。此外,它在UWP应用程序中也能工作,尽管UWP应用程序显然不支持底层Windows API。bxgwgixi2#
GetFinalPathNameByHandle
最终路径是路径完全解析后返回的路径。例如,对于指向“D:\yourdir”的名为“C:\tmp\mydir”的符号链接,最终文件系统路径将是“D:\yourdir”。