获取C#中的驱动器标签

获取C#中的驱动器标签

问题描述:

当我使用System.IO.DriveInfo.GetDrives()并查看其中一个驱动器的.VolumeLabel属性时,我看到“PATRIOT XT”,它确实是驱动器的卷标。获取C#中的驱动器标签

如果我打开“我的电脑”,而是看到“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:) 

我还没试过this自己,但在注册表中,查找

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

然后读取

DefaultLabel 

关键。另外警告!将无效的键/值写入注册表可能会严重损坏您的系统!在继续之前,确保你确定你在做什么。 Here is a resource to help you with accessing the registry programmatically.

+0

你有什么操作系统? Win XP Home没有名为“DriveIcons”的密钥! – Nayan 2010-05-16 13:53:47

+0

@Nayan - 我正在使用Windows 7. – 2010-05-16 13:55:55

+0

Vista中不存在密钥。 – Pindatjuh 2010-05-16 13:59:19

This看起来可能是一个解决方案。

+0

谢谢,但Win32_DiskDrive和Win32_PhysicalMedia似乎并没有保留我正在寻找的值。我已经尝试了几个Win32类,而且他们都没有看到! – Rick 2010-05-16 19:53:29

看起来我的电脑看着autorun.inf并使用[autorun]部分的label = value。

还是不太确定“DVD RW Drive”和“Floppy Disk Drive”标签来自哪里,但我猜可能是根据驱动器类型进行硬编码的。

我希望以下将帮助您:

[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; 
    } 
+0

此代码通常不好,并且不显示OP想要查看的内容。这个信息从'System.IO.DriveInfo.GetDrives()'获得很容易。 – GSerg 2017-04-19 13:57:52

它位于在autorun.inf的文件夹中。我对我的闪存驱动器卷标仅仅是16G, 而是通过把一个autorun.inf文件以下列文本 [自动运行] 标签=我的16 GB的闪存驱动器

,然后使用ATTRIB至+ S + H +该文件,它不会显示,除非我有 显示隐藏的文件和显示启用文件夹选项/视图下的系统文件。

要通过C#编程位于此,我真的没试过开的autorun.inf, 但它应该是直线前进,检查是否File.Exists(驱动器:\ autorun.inf的)忽略 的事实,它是+ s + h + r(以防万一某人设置了它),然后只打开它 并解析标签=行。如果实际上存在该文件,请使用自动运行标签而不是 卷标。

我仍然可以改变使用自动运行。inf label = tag即使在Windows 7中也可以修改标签。

感谢您提供关于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 
    } 

不幸的是,要得到这个信息而不用黑客和怪异的技巧,你需要使用P/Invoke技术。 有2个选项:

  1. 获取用户或系统设置的真实标签。这可以是“新卷”,“安装(\ Server)”,“Contoso Pro安装盘4”等。
  2. 完全按照它在资源管理器中显示的标签(我的电脑/此PC窗口)。这与(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.PARENTRELATIVEEDITINGSIGDN.NORMALDISPLAY代替SIGDN.PARENTRELATIVEEDITING

注意:对于第二种情况,有也使用ShGetFileInfo() 1调用方法,但无论如何,它调用这些方法,以及不够灵活,所以我不张贴在这里。

注意2:请记住,在此示例中优化SHGetNameFromIDList()的签名。如果驱动器标签仅用于临时(特别是在不时重新读取的情况下),则此示例引入小内存泄漏。为了避免它,最后一个参数声明为out IntPtr,然后使用类似

 var tmp = Marshal.PtrToStringUni(ppszName); 
    Marshal.FreeCoTaskMem(ppszName); 

注3:这个作品在Windows外壳,所以它会返回所期待的用户,不管这种标签的来源 - 卷标签,用户编辑,Autorun.inf文件或其他任何东西。