2014-10-26 3 views
2

У меня есть приложение, MSVC++, который выплевывает пути томов жесткого диска из файла ручками, что другие приложения, открытых в следующем формате строки:Жесткий путь Объем диска полный путь файла

\Device\HarddiskVolume4\Users\User\Documents\Visual Studio 2013\Projects\FileLocker\FileLocker\bin\Debug\Test.txt 

Я хотел бы, чтобы преобразовать эти пути к полным путям к этим файлам в Windows. Например, я хотел бы, чтобы преобразовать выше путь томов жесткого диска на полный путь к файлу Windows, с соответствующей буквой диска:

C:\Users\User\Documents\Visual Studio 2013\Projects\FileLocker\FileLocker\bin\Debug\Test.txt 

Я посмотрел в Интернете, но я не нашел четкий ресурс для делать это программно , Как это можно сделать?

ответ

4

Вы должны смотреть на одну из функций Windows API для управления томами:

Volume Management Functions

Вот пример из MSDN:

Displaying Volume Paths

#include <windows.h> 
#include <stdio.h> 

void DisplayVolumePaths(
     __in PWCHAR VolumeName 
     ) 
{ 
    DWORD CharCount = MAX_PATH + 1; 
    PWCHAR Names  = NULL; 
    PWCHAR NameIdx = NULL; 
    BOOL Success = FALSE; 

    for (;;) 
    { 
     // 
     // Allocate a buffer to hold the paths. 
     Names = (PWCHAR) new BYTE [CharCount * sizeof(WCHAR)]; 

     if (!Names) 
     { 
      // 
      // If memory can't be allocated, return. 
      return; 
     } 

     // 
     // Obtain all of the paths 
     // for this volume. 
     Success = GetVolumePathNamesForVolumeNameW(
      VolumeName, Names, CharCount, &CharCount 
      ); 

     if (Success) 
     { 
      break; 
     } 

     if (GetLastError() != ERROR_MORE_DATA) 
     { 
      break; 
     } 

     // 
     // Try again with the 
     // new suggested size. 
     delete [] Names; 
     Names = NULL; 
    } 

    if (Success) 
    { 
     // 
     // Display the various paths. 
     for (NameIdx = Names; 
       NameIdx[0] != L'\0'; 
       NameIdx += wcslen(NameIdx) + 1) 
     { 
      wprintf(L" %s", NameIdx); 
     } 
     wprintf(L"\n"); 
    } 

    if (Names != NULL) 
    { 
     delete [] Names; 
     Names = NULL; 
    } 

    return; 
} 

void __cdecl wmain(void) 
{ 
    DWORD CharCount   = 0; 
    WCHAR DeviceName[MAX_PATH] = L""; 
    DWORD Error    = ERROR_SUCCESS; 
    HANDLE FindHandle   = INVALID_HANDLE_VALUE; 
    BOOL Found    = FALSE; 
    size_t Index    = 0; 
    BOOL Success    = FALSE; 
    WCHAR VolumeName[MAX_PATH] = L""; 

    // 
    // Enumerate all volumes in the system. 
    FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName)); 

    if (FindHandle == INVALID_HANDLE_VALUE) 
    { 
     Error = GetLastError(); 
     wprintf(L"FindFirstVolumeW failed with error code %d\n", Error); 
     return; 
    } 

    for (;;) 
    { 
     // 
     // Skip the \\?\ prefix and remove the trailing backslash. 
     Index = wcslen(VolumeName) - 1; 

     if (VolumeName[0]  != L'\\' || 
      VolumeName[1]  != L'\\' || 
      VolumeName[2]  != L'?' || 
      VolumeName[3]  != L'\\' || 
      VolumeName[Index] != L'\\') 
     { 
      Error = ERROR_BAD_PATHNAME; 
      wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName); 
      break; 
     } 

     // 
     // QueryDosDeviceW does not allow a trailing backslash, 
     // so temporarily remove it. 
     VolumeName[Index] = L'\0'; 

     CharCount = QueryDosDeviceW(&VolumeName[4], DeviceName, ARRAYSIZE(DeviceName)); 

     VolumeName[Index] = L'\\'; 

     if (CharCount == 0) 
     { 
      Error = GetLastError(); 
      wprintf(L"QueryDosDeviceW failed with error code %d\n", Error); 
      break; 
     } 

     wprintf(L"\nFound a device:\n %s", DeviceName); 
     wprintf(L"\nVolume name: %s", VolumeName); 
     wprintf(L"\nPaths:"); 
     DisplayVolumePaths(VolumeName); 

     // 
     // Move on to the next volume. 
     Success = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName)); 

     if (!Success) 
     { 
      Error = GetLastError(); 

      if (Error != ERROR_NO_MORE_FILES) 
      { 
       wprintf(L"FindNextVolumeW failed with error code %d\n", Error); 
       break; 
      } 

      // 
      // Finished iterating 
      // through all the volumes. 
      Error = ERROR_SUCCESS; 
      break; 
     } 
    } 

    FindVolumeClose(FindHandle); 
    FindHandle = INVALID_HANDLE_VALUE; 

    return; 
} 

Для уточнения:

имя тома (или GUID) что-то вроде \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

Имени устройства является чем-то вроде \Device\HarddiskVolume1

буквы диска что-то вроде C:

FindFirst/NextVolume дает список имен томов.

QueryDosDevice дает имя устройства из имени тома.

GetVolumePathNamesForVolumeName дает вам букву диска из имени тома.

+0

Я знаю, что должен быть какой-то API, который это делает, но мне нужно знать, какой именно метод будет делать трюк, и в идеале я ищу программное решение. – Alexandru

+2

Этот пример из MSDN, похоже, делает именно то, что вы хотите: http://msdn.microsoft.com/en-us/library/cc542456%28v=vs.85%29.aspx Он отображает имя и путь каждого диск в вашей системе, просто выберите тот, который вы ищете. – kyflare

+0

Nice; большое спасибо! – Alexandru

Смежные вопросы