当我使用System.IO.DriveInfo.GetDrives()
并查看其中一个驱动器的.VolumeLabel
属性时,我看到“PATRIOT XT”,这确实是驱动器的卷标。
如果我打开“我的电脑”,而不是我看到“TrueCrypt Traveler Disk”,我似乎找不到以编程方式检索该值的任何方法,因为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
);
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:)
答案 0 :(得分:4)
不幸的是,为了获得这些信息而没有黑客和奇怪的技巧,你需要使用P / Invoke技术。 有两个选项:
要获得选项(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,还有使用ShGetFileInfo()
的1-call方法,但无论如何都会调用这些方法,而且灵活性较差,所以我不发帖它在这里。
注意2 :请注意,此示例中优化了SHGetNameFromIDList()
的签名。如果驱动器标签只是临时使用(特别是如果它不时被重新读取),则此示例会引入小内存泄漏。要避免它,请将最后一个参数声明为out IntPtr
,然后使用类似
var tmp = Marshal.PtrToStringUni(ppszName);
Marshal.FreeCoTaskMem(ppszName);
注3 :这适用于Windows shell,因此它将返回用户期望的内容,无论此标签的来源是什么 - 卷标,用户编辑,Autorun.inf文件或其他任何内容。< / p>
答案 1 :(得分:3)
感谢有关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
}
答案 2 :(得分:1)
看起来我的电脑看着autorun.inf并使用[autorun]部分中的label =值。
仍不太确定“DVD RW Drive”和“Floppy Disk Drive”标签的来源,但我猜他们可能会根据驱动器类型进行硬编码。
答案 3 :(得分:1)
我希望以下内容对您有所帮助:
[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;
}
答案 4 :(得分:0)
我自己没有尝试this,但在注册表中,请查找
HKLM/Software/Microsoft/Windows/CurrentVersion/Explorer/DriveIcons/[Drive-Letter]/
然后阅读
DefaultLabel
键。另外警告!向注册表写入无效的键/值会严重损坏您的系统!在继续之前,请确保您确定自己在做什么。 Here is a resource to help you with accessing the registry programmatically.
答案 5 :(得分:0)
This看起来可能是一个解决方案。
答案 6 :(得分:0)
它位于autorun.inf文件夹中。我的闪存驱动器的卷标仅为16G, 但是通过放置带有以下文本的autorun.inf文件 [自动运行] label =我的16千兆字节闪存驱动器
然后使用attrib到+ s + h + r文件,除非我有,否则它不显示 显示隐藏文件并在启用文件夹选项/视图下显示系统文件。
要通过C#以编程方式找到它,老实说我还没有尝试打开autorun.inf, 但它应该是直截了当的,检查File.Exists(Drive:\ autorun.inf)是否忽略 事实上它是+ s + h + r(以防万一有人设置它),然后打开它readonly 并解析label =行。实际上,如果文件存在,请使用自动运行标签代替 卷标。
即使在Windows 7中,我仍然可以更改使用autorun.inf label =标签来修改标签。
答案 7 :(得分:0)
最近,我遇到了可以解决的相同问题。以下是获取标签在Windows资源管理器中显示的方法:
C:\Windows\System32\shell32.dll
作为参考。using Shell32;
dynamic shellObject = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
var driveData = (Folder2)ShellObject.NameSpace(driveInfo.Name);
driveData.Name
将包含标签(例如:“本地磁盘(C :)”)。下面是完整的代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Shell32;
namespace VolumeLabels
{
static class Drives
{
[DebuggerDisplay("Name: '{Name,nq}', Path: '{Path,nq}'")]
public struct DriveNameInfo
{
public string Name { get; }
public string Path { get; }
public DriveNameInfo(string name, string path)
{
Name = name;
Path = path;
}
public override string ToString()
{
return Name;
}
}
private static dynamic _shellObject;
private static dynamic ShellObject => _shellObject ?? (_shellObject = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application")));
public static IEnumerable<DriveNameInfo> Get()
{
foreach (var driveInfo in DriveInfo.GetDrives())
{
var driveData = (Folder2)ShellObject.NameSpace(driveInfo.Name);
if (driveData == null)
yield break;
var driveDataSelf = driveData.Self;
yield return new DriveNameInfo(driveDataSelf.Name, driveDataSelf.Path);
}
}
}
class Program
{
static void Main(string[] args)
{
foreach (var driveNameInfo in Drives.Get())
Console.WriteLine(driveNameInfo);
Console.ReadKey(true);
}
}
}