2
我使用FindFirstFile()和协同函数来浏览C:\example\dir
的内容。我知道一个文件读取可以通过检查是否为d.dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0
来作为符号链接,连接点等。但是,我还没有找到一种方法来跟踪链接并查看它指向的位置。这甚至有可能吗?查找符号链接指向的位置(Windows)
我使用FindFirstFile()和协同函数来浏览C:\example\dir
的内容。我知道一个文件读取可以通过检查是否为d.dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0
来作为符号链接,连接点等。但是,我还没有找到一种方法来跟踪链接并查看它指向的位置。这甚至有可能吗?查找符号链接指向的位置(Windows)
要找到符号链接的目标,您必须打开符号链接。对象管理器取消引用链接并将句柄返回到目标位置。在该句柄上调用GetFinalPathNameByHandle将返回目标的路径名。
以下实现返回的目标位置,赋予了符号链接:
std::wstring GetLinkTarget(const std::wstring& a_Link) {
// Define smart pointer type for automatic HANDLE cleanup.
typedef std::unique_ptr<std::remove_pointer<HANDLE>::type,
decltype(&::CloseHandle)> FileHandle;
// Open file for querying only (no read/write access).
FileHandle h(::CreateFileW(a_Link.c_str(), 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr),
&::CloseHandle);
if (h.get() == INVALID_HANDLE_VALUE) {
h.release();
throw std::runtime_error("CreateFileW() failed.");
}
const size_t requiredSize = ::GetFinalPathNameByHandleW(h.get(), nullptr, 0,
FILE_NAME_NORMALIZED);
if (requiredSize == 0) {
throw std::runtime_error("GetFinalPathNameByHandleW() failed.");
}
std::vector<wchar_t> buffer(requiredSize);
::GetFinalPathNameByHandleW(h.get(), buffer.data(),
static_cast<DWORD>(buffer.size()),
FILE_NAME_NORMALIZED);
return std::wstring(buffer.begin(), buffer.end() - 1);
}
代码中存在一个错误:文件句柄在函数结束时未关闭。它只在GetFinalPathNameByHandleW()返回0时关闭。 – Andy
@Andy:的确如此。还有另一个bug,这是不太明显的:如果'std :: vector'抛出一个异常,那么文件句柄也不会被关闭。这可以通过使用通过'HANDLE'实现RAII的库来解决。我会添加适当的评论。 – IInspectable
@IInspectable:在C++ 11中,你可以使用'std :: unique_ptr'或'std :: shared_ptr'(或等价的boost)作为RAII包装器,它们都支持定制的删除器,'CloseHandle()'可以用于删除者。 –