在C#中获取驱动器标签

当我使用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 ); 
可拆卸(A :)
固定(C :)
 CDRom(D :)
爱国者XT(E :)
备份(Y :)
数据(Z :)

我的电脑详情视图显示:

软盘驱动器(A :)
本地磁盘(C :)
 DVD RW驱动器(D :)
 TrueCrypt Traveler磁盘(E :)
备份(Y :)
数据(Z :)

感谢关于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技术。 有两种选择:

  1. 获取用户或系统设置的真实标签。 这可能是“ 新卷 ”,“ 安装(\ Server) ”,“ Contoso Pro安装盘4 ”等。
  2. 获取与Explorer(我的电脑/此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.PARENTRELATIVEEDITING替换为SIGDN.PARENTRELATIVEEDITINGSIGDN.NORMALDISPLAY

注意 :对于选项2,还有使用ShGetFileInfo() 1-call方法,但它仍然调用这些方法,并且灵活性较差,所以我不在此处发布。

注意2 :请记住, SHGetNameFromIDList()的签名在此示例中已经过优化。 如果驱动器标签只是临时使用(特别是如果它不时被重新读取),则此示例会引入小内存泄漏。 为了避免它,将last参数声明为out IntPtr ,然后使用类似的东西

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

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

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

仍不太确定“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; } 

我自己没试过,但在注册表中,寻找

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

然后阅读

 DefaultLabel 

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

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

它位于autorun.inf文件夹中。 我的闪存驱动器的卷标仅为16G,但是通过放置带有以下文本的autorun.inf文件[autorun] label =我的16 GB闪存驱动器

然后使用attrib到+ s + h + r文件,除非我显示隐藏文件并在启用文件夹选项/视图下显示系统文件,否则它不会显示。

为了通过C#以编程方式定位,我老实说没有尝试打开autorun.inf,但它应该是直接的,检查File.Exists(Drive:\ autorun.inf)是否忽略了它是+ s + h +的事实r(以防万一有人设置它),然后打开它readonly并解析label =行。 如果实际上存在该文件,请使用自动运行标签而不是卷标。

即使在Windows 7中,我仍然可以更改使用autorun.inf label =标签来修改标签。