在C#中获取驱动器标签

Ric*_*ick 13 c# drive

当我使用System.IO.DriveInfo.GetDrives()并查看.VolumeLabel其中一个驱动器的属性时,我看到"PATRIOT XT",这确实是驱动器的卷标.

如果我打开"我的电脑",而不是我看到"TrueCrypt Traveler磁盘",我似乎无法找到任何方式以编程方式检索该值,因为没有任何DriveInfo属性保存该值.我也试过通过WMI查询信息Win32_LogicalDisk,但是没有属性包含那个值.

那么任何想法My Computer使用的标签都被称为,更重要的是,如何以编程方式检索它?

编辑:要清楚,这是我正在使用的代码,然后是它输出的内容,接下来是我在"我的电脑"中看到的内容(这是我要复制的内容):

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
    );
Run Code Online (Sandbox Code Playgroud)
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:)

Mik*_*rov 6

不幸的是,要在没有黑客和奇怪技巧的情况下获得这些信息,您需要使用 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;
    }
Run Code Online (Sandbox Code Playgroud)

对于选项 (2),替换SIGDN.PARENTRELATIVEEDITINGSIGDN.PARENTRELATIVESIGDN.NORMALDISPLAY

注意:对于选项 2,还有 1-call 方法 using ShGetFileInfo(),但它无论如何都会调用这些方法,并且不太灵活,所以我不在这里发布它。

注意 2:请记住,SHGetNameFromIDList()本示例中优化了 的签名。如果驱动器标签只是临时使用(尤其是不时重新读取时),则此示例会引入少量内存泄漏。为了避免它,将最后一个参数声明为out IntPtr,然后使用类似

     var tmp = Marshal.PtrToStringUni(ppszName);
     Marshal.FreeCoTaskMem(ppszName);
Run Code Online (Sandbox Code Playgroud)

注意 3:这适用于 Windows shell,因此它将返回用户期望的内容,无论此标签的来源如何 - 卷标、用户编辑、Autorun.inf 文件或其他任何内容。


Bob*_*man 0

我自己没有尝试过但在注册表中查找

HKLM/Software/Microsoft/Windows/CurrentVersion/Explorer/DriveIcons/[Drive-Letter]/
Run Code Online (Sandbox Code Playgroud)

然后阅读

DefaultLabel
Run Code Online (Sandbox Code Playgroud)

钥匙。另请警告!将无效的键/值写入注册表可能会严重损坏您的系统!在继续之前,请确保您确定自己在做什么。以下资源可帮助您以编程方式访问注册表。