How can I read the "friendly name" for a mapped network share?
Asked Answered
R

2

6

Basics: C# WinForms desktop application targeting Dot Net 4.

I am enumerating all drives on a system using System.IO.DriveInfo. This works quite well and can also tell me what type of drive it is (fixed/network/cd-rom, etc). It can also give me the VolumeLabel - this works as desired on local drives, but for mapped network drives it gives you the VolumeLabel of the logical disk as defined on the host computer. In Windows Explorer, you can give any mapped drive a friendly name. Is there a way to programmatically retrieve this friendly name? This name is obviously the one that is familiar to the person using the computer.

For example, in the image below both "Critical" and "NonCritical" might be different shares on the same logical disk with a volume name "Data" on the host computer. Querying WMI for VolumeName returns "Data", and the other queries return just the drive letter, or else nothing.

Example

I have looked at the info available through WMI (see: How to programmatically discover mapped network drives on system and their server names?) but there doesn't seem to be a property that returns this friendly name. I've looked at Caption, Description, SystemName, and VolumeName - like this:

private void NetworkDrives()
{
    try
    {
        var searcher = new ManagementObjectSearcher(
            "root\\CIMV2",
            "SELECT * FROM Win32_MappedLogicalDisk");

        TreeNode share;
        TreeNode property;

        foreach (ManagementObject queryObj in searcher.Get())
        {
            share = new TreeNode("Name:" + queryObj["Name"]);                    
            share.Nodes.Add("Caption: " + queryObj["Caption"]);
            share.Nodes.Add("Description: " + queryObj["Description"]);
            share.Nodes.Add("SystemName: " + queryObj["SystemName"]);
            share.Nodes.Add("VolumeName: " + queryObj["VolumeName"]);
            share.Nodes.Add("DeviceID: " + queryObj["DeviceID"]);
            treeView1.Nodes.Add(share);
        }
    }
    catch (ManagementException ex)
    {
        MessageBox.Show("An error occurred while querying for WMI data: " + ex.Message);
    }
}

Thanks in advance.

Reimport answered 25/2, 2014 at 13:42 Comment(2)
I am unable to add a mapped drive myself to test this out, but have you seen this discussion thread (and the suggestion to query Win32_DiskDrive)?Dishman
@ledbutter: Yes I have. Like they say Caption and Description don't give the info we want. I haven't found a WMI property yet that returns this specific information. See my comment on JPBlanc's answer for where this is in the registry.Reimport
C
2

Using Win32_Logicaldisk you've got :

DeviceID     : P:
DriveType    : 4
ProviderName : \\localhost\download\Chic
FreeSpace    : 26406707200
Size         : 500000878592
VolumeName   :

For DriveType 4, you will find the Volume in the last part of the UNC name. You just have to use a regular exprssion to get it.


Edited according to your comment.

Using PowerShell (not far from C#) it can be written :

cd HKCU:
Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2 | where {$_.name -like '*##localhost#download#Chic'} | % {(Get-ItemProperty -LiteralPath $_.name -Name _LabelFromReg)._LabelFromReg} 
Cathiecathleen answered 25/2, 2014 at 20:41 Comment(5)
Regex over the top. Read backwards until you find the first path sep. Split on path sep would work.Endymion
@JPBlanc: Ok, ProviderName is available on Win32_MappedLogicalDisk as well. It returns the full share path which is a good start, although it is not exactly what I was hoping for. The default label for a mapped network drive is based on the the ProviderName as you describe. The thing is you can edit that label to anything you want - e.g. \\Srv\Share1 will map as "Share1 on Srv (M:)" by default but you can rename it in Explorer to "Server Stuff (M:)". ProviderName still returns \\Srv\Share1.Reimport
The correct values are in the Registry in the _LabelFromReg value in the key \HKEY_USERS\<SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\##Srv#Share1. It only exists if you have relabeled a share. I'm not going jumping through all the hoops required to extract that value!Reimport
@Nicolas, you should add this to your question or propose it as a first answer, I was not knowing it. As it is an explorer.exe feature, I don't think that you can retreive it with WMI.Cathiecathleen
@JPBLanc, I'll add it as a possible answer. I only found that out by browsing through likely areas in my own registry today with Regedit.Reimport
R
2

The correct values are stored in the Registry in the value _LabelFromReg of the key HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints‌​2\##ServerName#ShareName. This value only exists for a share if you have relabeled that share.

EDIT: Here is a working example, albeit without proper error checking. Thanks JPBlanc for the registry shortcut to use HKEY_CURRENT_USER\etc instead of HKEY_USERS\<SID>\etc.

private string GetDriveLabel(DriveInfo drv)
{
    string drvName;
    string drvLabel;
    string pvdr = "";

    //Start off with just the drive letter
    drvName = "(" + drv.Name.Substring(0,2) + ")";

    //Use the volume label if it is not a network drive
    if (drv.DriveType != DriveType.Network)
    {
        drvLabel = drv.VolumeLabel;
        return drvLabel + " " + drvName;
    }

    //Try to get the network share name            
    try
    {
        var searcher = new ManagementObjectSearcher(
            "root\\CIMV2",
            "SELECT * FROM Win32_MappedLogicalDisk WHERE Name=\"" + drv.Name.Substring(0,2) + "\"");

        foreach (ManagementObject queryObj in searcher.Get())
        {
            pvdr = @queryObj["ProviderName"].ToString();
        }
    }
    catch (ManagementException ex)
    {
        pvdr = "";
    }

    //Try to get custom label from registry
    if (pvdr != "")
    {   
        pvdr = pvdr.Replace(@"\", "#");
        drvLabel = (string)Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\" + pvdr, "_LabelFromReg", "");
        if (string.IsNullOrEmpty(drvLabel))
        {
            //If we didn't get the label from the registry, then extract the share name from the provider
            drvLabel = pvdr.Substring(pvdr.LastIndexOf("#") + 1);
        }
        return drvLabel + " " + drvName;
    }
    else
    {
        //No point in trying the registry if we don't have a provider name
        return drvName;
    }
}
Reimport answered 26/2, 2014 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.