When I use System.IO.DriveInfo.GetDrives()
and look at the .VolumeLabel
property of one of the drives, I see "PATRIOT XT", which is indeed the drive's volume label.
If I open "My Computer", instead I see "TrueCrypt Traveler Disk", and I can't seem to find any way to programmatically retrieve that value as none of the DriveInfo
properties hold that value. I also tried querying the information via WMI's Win32_LogicalDisk
, but no properties contained that value there either.
So any idea what the label My Computer uses is called, and more importantly, how to programmatically retrieve it?
EDIT: To be clear, here's the code I'm using, followed by what it outputs, followed by what I see in My Computer (which is what I want to duplicate):
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:)
My Computer details view displays:
Floppy Disk Drive (A:) Local Disk (C:) DVD RW Drive (D:) TrueCrypt Traveler Disk (E:) Backup (Y:) Data (Z:)
As you can see, the volume label for the C drive is Windows and the volume serial number is C1F3-A79E.
Right-click the drive you want to rename. In the drop-down menu that appears, select Properties. In the Properties window, on the General tab, type a new name in the Label box (A), click Apply (B), and then click OK (C).
A volume label, sometimes called a volume name, is a unique name assigned to a hard drive, disc, or other media. It's not required in Windows, but it's often useful to give a name to a drive to help identify its use in the future.
Unfortunately, to get this information without hacks and weird tricks, you need to use the P/Invoke technique. There are 2 options:
To get the information as explained in option (1), you'll have to use the following code:
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;
}
For option (2), replace SIGDN.PARENTRELATIVEEDITING
with SIGDN.PARENTRELATIVE
or SIGDN.NORMALDISPLAY
.
Note: for option 2, there's also 1-call method using ShGetFileInfo()
, but it calls these methods anyway, and is less flexible, so I do not post it here.
Note 2: keep in mind, the signature of SHGetNameFromIDList()
is optimized in this example. In case the drive label is used only temporary (especially if it is re-read from time to time) this example introduces small memory leak. To avoid it, declare last parameter as out IntPtr
, and then use something like
var tmp = Marshal.PtrToStringUni(ppszName);
Marshal.FreeCoTaskMem(ppszName);
Note 3: this works over Windows shell, so it will return what user expects, regardless of the source of this label - volume label, user edit, Autorun.inf file or anything else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With