Получить метку диска в C # - PullRequest
13 голосов
/ 16 мая 2010

Когда я использую System.IO.DriveInfo.GetDrives() и смотрю на свойство .VolumeLabel одного из дисков, я вижу «PATRIOT XT», который действительно является меткой тома диска.

Если я открою «Мой компьютер», вместо этого я вижу «TrueCrypt Traveler Disk», и я не могу найти какой-либо способ программно получить это значение, поскольку ни одно из свойств DriveInfo не содержит это значение. Я также попытался запросить информацию через WMI Win32_LogicalDisk, но ни одно из свойств не содержало там этого значения.

Значит, есть идея, как называется метка "Мой компьютер", и, что более важно, как ее программно получить?

РЕДАКТИРОВАТЬ: Чтобы быть ясным, вот код, который я использую, после чего он выводит, а затем то, что я вижу в моем компьютере (что я хочу дублировать):

foreach (DriveInfo DI in DriveInfo.GetDrives())
    richTextBox1.AppendText(
        (
            DI.IsReady ?
            (DI.VolumeLabel.Length == 0 ? DI.DriveType.ToString() : DI.VolumeLabel) :
            DI.DriveType.ToString()
        )
        +
        " (" + DI.Name.Replace("\\", "") + ")"
        + Environment.NewLine
    );
Removable (A:)
Fixed (C:)
CDRom (D:)
PATRIOT XT (E:)
Backup (Y:)
Data (Z:)

Отображение сведений о моем компьютере:

Floppy Disk Drive (A:)
Local Disk (C:)
DVD RW Drive (D:)
TrueCrypt Traveler Disk (E:)
Backup (Y:)
Data (Z:)

Ответы [ 7 ]

4 голосов
/ 22 марта 2015

К сожалению, чтобы получить эту информацию без хаков и странных уловок, вам нужно использовать технику P / Invoke. Есть 2 варианта:

  1. Получить реальную метку, установленную пользователем или системой. Это могут быть " Новый том ", " Установка (\ Server) ", " Установочный диск Contoso Pro 4 " и т. Д.
  2. Получите метку в точности так, как она отображается в Проводнике (Мой компьютер / Это окно ПК). Это то же самое, что (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 или чего-либо еще.

3 голосов
/ 15 октября 2011

Спасибо за отзыв о autorun.inf. Вот фрагмент C #, который я создал для получения метки.

private string GetDriveLabelFromAutorunInf(string drivename)
    {
        try
        {
            string filepathAutorunInf = Path.Combine(drivename, "autorun.Inf");
            string stringInputLine = "";
            if (File.Exists(filepathAutorunInf))
            {
                StreamReader streamReader = new StreamReader(filepathAutorunInf);
                while ((stringInputLine = streamReader.ReadLine()) != null) 
                  {
                      if (stringInputLine.StartsWith("label="))
                          return stringInputLine.Substring(startIndex:6);
                  }
                return "";
            }
            else return "";
        }
        #region generic catch exception, display message box, and terminate
        catch (Exception exception)
        {
            System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(exception, true);
            MessageBox.Show(string.Format("{0} Exception:\n{1}\n{2}\n\n{3}\n\nMethod={4}   Line={5}   Column={6}",
                    trace.GetFrame(0).GetMethod().Module,
                    exception.Message,
                    exception.StackTrace,
                    exception.ToString(),
                    trace.GetFrame(0).GetMethod().Name,
                    trace.GetFrame(0).GetFileLineNumber(),
                    trace.GetFrame(0).GetFileColumnNumber()),
                "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            Environment.Exit(1);
            return "";      // to keep compiler happy
        }
        #endregion
    }
1 голос
/ 17 мая 2010

Надеюсь, вам поможет следующее:

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern bool GetVolumeInformation(string Volume,
        StringBuilder VolumeName, uint VolumeNameSize,
        out uint SerialNumber, out uint SerialNumberLength, out uint flags,
        StringBuilder fs, uint fs_size);

    private void Form1_Load(object sender, EventArgs e)
    {
        uint serialNum, serialNumLength, flags;
        StringBuilder volumename = new StringBuilder(256);
        StringBuilder fstype = new StringBuilder(256);
        bool ok = false;
        Cursor.Current = Cursors.WaitCursor;
        foreach (string drives in Environment.GetLogicalDrives())
        {
            ok = GetVolumeInformation(drives, volumename, (uint)volumename.Capacity - 1, out serialNum,
                                   out serialNumLength, out flags, fstype, (uint)fstype.Capacity - 1);
            if (ok)
            {
                lblVolume.Text = lblVolume.Text + "\n Volume Information of " + drives + "\n";
                lblVolume.Text = lblVolume.Text + "\nSerialNumber of is..... " + serialNum.ToString() + " \n";
                if (volumename != null)
                {
                    lblVolume.Text = lblVolume.Text + "VolumeName is..... " + volumename.ToString() + " \n";
                }
                if (fstype != null)
                {
                    lblVolume.Text = lblVolume.Text + "FileType is..... " + fstype.ToString() + " \n";
                }
            }
            ok = false;
        }
        Cursor.Current = Cursors.Default;
    }
1 голос
/ 17 мая 2010

Похоже, что мой компьютер смотрит на autorun.inf и использует значение label = из секции [autorun].

Все еще не совсем уверен, откуда берутся ярлыки "DVD RW Drive" и "Floppy Disk Drive", но я думаю, что они могут быть жестко закодированы в зависимости от типа привода.

0 голосов
/ 08 июля 2010

Он находится в папке autorun.inf.Моя метка тома для моей флешки просто 16G, но добавив файл autorun.inf со следующим текстом [autorun] label = Мой 16-гигабайтный флэш-накопитель

, а затем используя атрибут при + s + h + rфайл, он не будет отображаться, пока я не покажу скрытые файлы И не покажу системные файлы в папке «Параметры / просмотр включена».

Чтобы программно найти это через C #, я, честно говоря, не пытался открыть автозапуск.inf, но это должно быть прямо, проверьте, не существует ли File.Exists (Drive: \ autorun.inf), игнорируя тот факт, что он + s + h + r (на всякий случай, если кто-то его установил), затем откройте его только для чтения и проанализируйтеметка = строка.Если файл действительно присутствует, используйте метку автозапуска вместо метки тома.

Я все еще могу изменить, используйте метку autorun.inf label = даже в Windows 7 для изменения метки.

0 голосов
/ 16 мая 2010

Это , похоже, может быть решением.

0 голосов
/ 16 мая 2010

Я не пробовал это сам, но в реестре поищу

HKLM/Software/Microsoft/Windows/CurrentVersion/Explorer/DriveIcons/[Drive-Letter]/

затем прочитайте

DefaultLabel

ключ. Также ПРЕДУПРЕЖДЕНИЕ! запись неверных ключей / значений в реестр может серьезно повредить вашу систему! Будьте уверены, что вы уверены, что вы делаете, прежде чем продолжить. Вот ресурс, который поможет вам с программным доступом к реестру.

...