问题
Here is my code snippet:
char existingTarget[MAX_PATH];
HANDLE hFile = CreateFile(linkPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
GetFinalPathNameByHandle(hFile, existingTarget, MAX_PATH, FILE_NAME_OPENED);
CloseHandle(hFile);
}
However, existingTarget
is coming out to be \\?\C:\mydir\etc
. How can I get it to return just C:\mydir\etc
?
Note: I don't want to check for the string \\?\
and just memmove
it, it's a bit too hackish of a solution for this program.
回答1:
how can I get it to return just C:\mydir\etc
You cannot. VOLUME_NAME_DOS
and VOLUME_NAME_GUID
always use that format, and is documented as such:
The string that is returned by this function uses the
\\?\
syntax.
See the example results in the Community Additions section of the documentation.
Note: I don't want to check for the string
\\?\
and just memmove it, its a bit too hackish of a solution for this program.
That is the easiest solution. Otherwise, you have to use other APIs to translate the returned path into a more human-readable path. Such as using the result of VOLUME_NAME_NT
with QueryDosDevice(), or using the result of VOLUME_NAME_GUID
with GetVolumePathNamesForVolumeName().
回答2:
I know, you don't want to check for \\?\
and remove it, but as Remy explains in his answer, that's the easiest solution. However, you should be careful, because local paths and network paths have different prefixes. As you know, a local path starts with \\?\
, but a network path starts with \??\UNC\
, for example:
\\?\UNC\My server\My share\Directory
As a result, based on your code, my solution to remove the prefixes is as follows:
char existingTarget[MAX_PATH];
HANDLE hFile = CreateFileA(linkPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
DWORD ret = GetFinalPathNameByHandleA(hFile, existingTarget, MAX_PATH, FILE_NAME_OPENED);
CloseHandle(hFile);
// Check whether existingTarget is large enough to hold the final path.
if (ret < MAX_PATH)
{
// The local path prefix is also a prefix of the network path prefix.
// Therefore, look for the network path prefix first.
// Please note that backslashes have to be escaped.
std::string targetPath(existingTarget);
if (targetPath.substr(0, 8).compare("\\\\?\\UNC\\") == 0)
{
// In case of a network path, replace `\\?\UNC\` with `\\`.
targetPath = "\\" + targetPath.substr(7);
}
else if (targetPath.substr(0, 4).compare("\\\\?\\") == 0)
{
// In case of a local path, crop `\\?\`.
targetPath = targetPath.substr(4);
}
}
}
If needed, you can still use memmove()
to copy targetPath
into another variable.
来源:https://stackoverflow.com/questions/31439011/getfinalpathnamebyhandle-result-without-prepended