Вот мой фрагмент кода:
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);
}
Тем не мение, existingTarget
выходит, чтобы быть \\?\C:\mydir\etc
, Как я могу заставить его вернуться просто C:\mydir\etc
?
Заметка: Я не хочу проверять строку \\?\
и просто memmove
Это слишком хакерское решение для этой программы.
как я могу заставить его вернуть только C: \ mydir \ etc
Ты не можешь. VOLUME_NAME_DOS
а также VOLUME_NAME_GUID
всегда использовать этот формат, и задокументировано как таковой:
Строка, возвращаемая этой функцией, использует
\\?\
синтаксис.
Увидеть пример результатов в разделе дополнений сообщества документация.
Примечание: я не хочу проверять строку
\\?\
и просто запомни это, слишком хакерское решение для этой программы.
Это самое простое решение. В противном случае вам придется использовать другие API для перевода возвращаемого пути в более понятный для человека путь. Например, используя результат VOLUME_NAME_NT
с QueryDosDevice()
, или используя результат VOLUME_NAME_GUID
с GetVolumePathNamesForVolumeName()
.
Я знаю, вы не хотите проверять \\?\
и удалить его, но, как объясняет Реми в своем ответ, это самое простое решение. Однако вы должны быть осторожны, потому что локальные и сетевые пути имеют разные префиксы. Как вы знаете, локальный путь начинается с \\?\
, но сетевой путь начинается с \??\UNC\
, например:
\\?\UNC\My server\My share\Directory
В результате, основываясь на вашем коде, мое решение удалить префиксы выглядит следующим образом:
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);
}
}
}
При необходимости вы все еще можете использовать memmove()
копировать targetPath
в другую переменную.