如何使用 GetFinalPathNameByHandle 来解析指向本地目录的符号链接?
Posted
技术标签:
【中文标题】如何使用 GetFinalPathNameByHandle 来解析指向本地目录的符号链接?【英文标题】:How does one use GetFinalPathNameByHandle to resolve a symbolic link to a local directory? 【发布时间】:2018-05-04 15:03:13 【问题描述】:我有以下代码:
std::wstring GetSymbolicLinkTarget(std::wstring const& linkPath)
TCHAR path[MAX_PATH];
CAutoFile hFile = CreateFile( linkPath.c_str(),
FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_REPARSE_POINT | FILE_FLAG_OPEN_REPARSE_POINT,
0);
if (INVALID_HANDLE_VALUE != hFile)
auto rcode = GetFinalPathNameByHandle(hFile, path, MAX_PATH, FILE_NAME_NORMALIZED);
switch (rcode)
case ERROR_PATH_NOT_FOUND:
return std::wstring();
case ERROR_NOT_ENOUGH_MEMORY:
return std::wstring();
case ERROR_INVALID_PARAMETER:
return std::wstring();
case ERROR_ACCESS_DENIED:
return std::wstring();
default:
break;
;
if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
return std::wstring(path + 4, path + MAX_PATH);
else
return std::wstring(path, path + MAX_PATH);
return std::wstring();
我像这样创建一个符号链接:
e:
cd Projects\ProjectA\IDE_Files
mklink /D src ..
然后在一些代码中我调用上面的函数,根据文档说:
e:\Projects\ProjectA\IDE_Files\src
应该解决:
e:\Projects\ProjectA
它只是返回输入路径:
e:\Projects\ProjectA\IDE_Files\src
rcode
结果包含路径中的字符数。不是错误代码。
为什么无法返回我期望的结果?
【问题讨论】:
To do this, you open the symbolic link。所以删除 FILE_FLAG_OPEN_REPARSE_POINT 来解决问题。 谢谢汉斯!把它作为一个答案,我会接受的。 随意使用您发现的内容来完成您开始的 Q+A。 另外,请求 0 访问,而不是FILE_READ_EA
。 CreateFile
实际上至少会请求SYNCHRONIZE | FILE_READ_ATTRIBUTES
,但让它为你决定。并且请求读写删除共享只是源代码中毫无意义的文本,因为您没有请求数据访问;使用 0 表示共享模式。最后,不要在属性中包含FILE_ATTRIBUTE_REPARSE_POINT
。你不能设置这个属性;它是在创建重解析点时设置的。
【参考方案1】:
这个答案来自Hans Passant:
问题主要是由于使用了FILE_FLAG_OPEN_REPARSE_POINT
标志,它执行以下操作:
OpenFileById 函数将打开文件或重新解析 点,取决于 FILE_FLAG_OPEN_REPARSE_POINT 标志的使用。 [source].
这是最终代码(上面的 cmets 进行了多项修复。):
std::wstring GetSymbolicLinkTarget(std::wstring const& linkPath)
TCHAR path[MAX_PATH];
CAutoFile hFile = CreateFile( linkPath.c_str(),
0,
0,
0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
0);
if (INVALID_HANDLE_VALUE != hFile)
auto rcode = GetFinalPathNameByHandle(hFile, path, MAX_PATH, FILE_NAME_NORMALIZED);
if (rcode)
if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
return std::wstring(path + 4, path + rcode);
else
return std::wstring(path, path + rcode);
return std::wstring();
【讨论】:
GetFinalPathNameByHandle
返回的不是错误代码,而是字符串的长度.. 如果它返回 0,您需要调用 GetLastError
并且它的值已经与 ERROR_*
进行比较
直接来自documentation:"如果函数成功,返回值是lpszFilePath接收到的字符串的长度,在TCHAR
s。[...]如果函数因任何其他原因失败,返回值为零。要获取扩展错误信息,请调用 GetLastError
。" 此外,您的错误报告(某些错误条件为空字符串,其他错误条件为异常)的混合是不寻常的.它增加了调用代码的复杂性。这与抽象应该做的相反。
是的,我没有意识到返回值不包含错误代码。至于开关...我正在使用它们进行调试以查看可能发生的代码...以上是关于如何使用 GetFinalPathNameByHandle 来解析指向本地目录的符号链接?的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]
如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?