К сожалению, чтобы получить эту информацию без хаков и странных уловок, вам нужно использовать технику P / Invoke.
Есть 2 варианта:
- Получить реальную метку, установленную пользователем или системой. Это могут быть " Новый том ", " Установка (\ Server) ", " Установочный диск Contoso Pro 4 " и т. Д.
- Получите метку в точности так, как она отображается в Проводнике (Мой компьютер / Это окно ПК). Это то же самое, что (1), но оно следует пользовательским настройкам, установленным в диалоговом окне «Свойства папки», например, «Скрыть букву диска». Пример: " Новый том (Q:) "
Чтобы получить информацию, как описано в варианте (1), вам необходимо использовать следующий код:
public const string SHELL = "shell32.dll";
[DllImport(SHELL, CharSet = CharSet.Unicode)]
public static extern uint SHParseDisplayName(string pszName, IntPtr zero, [Out] out IntPtr ppidl, uint sfgaoIn, [Out] out uint psfgaoOut);
[DllImport(SHELL, CharSet = CharSet.Unicode)]
public static extern uint SHGetNameFromIDList(IntPtr pidl, SIGDN sigdnName, [Out] out String ppszName);
public enum SIGDN : uint
{
NORMALDISPLAY = 0x00000000,
PARENTRELATIVEPARSING = 0x80018001,
DESKTOPABSOLUTEPARSING = 0x80028000,
PARENTRELATIVEEDITING = 0x80031001,
DESKTOPABSOLUTEEDITING = 0x8004c000,
FILESYSPATH = 0x80058000,
URL = 0x80068000,
PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
PARENTRELATIVE = 0x80080001
}
//var x = GetDriveLabel(@"C:\")
public string GetDriveLabel(string driveNameAsLetterColonBackslash)
{
IntPtr pidl;
uint dummy;
string name;
if (SHParseDisplayName(driveNameAsLetterColonBackslash, IntPtr.Zero, out pidl, 0, out dummy) == 0
&& SHGetNameFromIDList(pidl, SIGDN.PARENTRELATIVEEDITING, out name) == 0
&& name != null)
{
return name;
}
return null;
}
Для варианта (2) заменить SIGDN.PARENTRELATIVEEDITING
на SIGDN.PARENTRELATIVEEDITING
или SIGDN.NORMALDISPLAY
.
Примечание : для варианта 2 также есть метод 1-call, использующий ShGetFileInfo()
, но он все равно вызывает эти методы и менее гибок, поэтому я не публикую его здесь.
Примечание 2 : имейте в виду, что в этом примере оптимизирована подпись SHGetNameFromIDList()
. В случае, если метка диска используется только временно (особенно если она перечитывается время от времени), в этом примере возникает небольшая утечка памяти. Чтобы избежать этого, объявите последний параметр как out IntPtr
, а затем используйте что-то вроде
var tmp = Marshal.PtrToStringUni(ppszName);
Marshal.FreeCoTaskMem(ppszName);
Примечание 3 : это работает через оболочку Windows, поэтому она возвращает то, что ожидает пользователь, независимо от источника этой метки - метки тома, редактирования пользователем, файла Autorun.inf или чего-либо еще.