pnp

Hi

Are there any way in C# to translate a UNC path to a drive letter used on the local machine.

E.g.if my drive s:\ is mounted to \\server\Shared, then i would like to be able to feed a method with \\server\Shared\lib\file.ext and get in return s:\lib\file.ext.

My first idea was to use DriveInfo.GetDrives, iterate through each and see if they had some information. It doesn't seem like they hold any usefull information for this purpose.

Are there any other way to get this information Performance in this exact situation is not very important, so iterating through some values to search for the first part of the UNC will be ok.

I hope someone has been here before, and can help me figure this out.

/Anders


Re: Visual C# General Translate UNC path to local mounted driveletter.

John Willemse

You can use the registry to get the currently mapped network drives and compare them:

string UNCtoMappedDrive(string uncPath)
{
Microsoft.Win32.RegistryKey rootKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("network");

foreach (string subKey in rootKey.GetSubKeyNames())
{
Microsoft.Win32.RegistryKey mappedDriveKey = rootKey.OpenSubKey(subKey);

if (string.Compare((string)mappedDriveKey.GetValue("RemotePath", ""), uncPath, true) == 0)
return subKey.ToUpperInvariant() + @":\";
}

return uncPath;
}

If the UNC path is not found, the original string is returned unmodified, otherwise the network drive in the form X:\ is returned.





Re: Visual C# General Translate UNC path to local mounted driveletter.

pnp

Hi John

Thanks for the feedback. I have found another example using System.Management. This works for me as well. I am not aware of any advantages with one or the other. Do you know if any of them require local adminstrator rights i.e

Here is my sample - a bit larger than yours... :-)
Usage would be :
UncConverter unc = UncConverter.GetInstance();
unc.ConvertToDrive("\\server\share\directory");

The singleton pattern ensures that i only have to look up the objects once - it can probably be improved.. But it seems to do the trick for my application.

But thanks for taking your time anyway.

/Anders

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Management;
using System.Threading;
using System.IO;

namespace myNamespace
{
public class UncConverter
{
#region getInstance
/// <summary>
/// Returns an instance of the UNCConverter
/// </summary>
/// <returns>The UNCConverter instance</returns>
public static UncConverter getInstance()
{
if (Object.Equals(_instance, null))
{
UncConverter instance = new UncConverter();
if (Object.Equals(_instance, null))
_instance = instance;
}
return _instance;
}
#endregion

#region Variables
private static UncConverter _instance=null;
private List<UncToDrive> _drives;
private bool _loaded = false;
#endregion

#region Constructor
/// <summary>
/// Private constructor. Loads the drive info from management objects.
/// </summary>
private UncConverter()
{
ThreadStart loaderStart = new ThreadStart(LoadDrives);
Thread loader = new Thread(loaderStart);
loader.Start();
}
#endregion

#region Loader Thread
/// <summary>
/// Uses ManagementObjectSearch to load all local and remote name mappings to the _drives list.
/// </summary>
private void LoadDrives()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT RemoteName, LocalName FROM Win32_NetworkConnection");
List<UncToDrive> drives = new List<UncToDrive>();
foreach (ManagementObject obj in searcher.Get())
{
object localObj = obj["LocalName"];
if (!Object.Equals(localObj, null))
drives.Add(new UncToDrive(obj["RemoteName"].ToString(), localObj.ToString()));
}
_drives = drives;
_loaded = true;
}
#endregion

#region Searchers
/// <summary>
/// Converts the input source to a source with drive letter if possible. Returns source if no drive letter was found
/// </summary>
/// <param name="source">The source path in UNC style</param>
/// <returns>The source in mounted drive letter if possible</returns>
public string ConvertToDrive(string uncSource)
{
if (_loaded)
{
Match match;
foreach (UncToDrive drive in _drives)
{
match = Regex.Match(uncSource, drive.Regex, RegexOptions.IgnoreCase);
if (match.Success)
{
string result = uncSource.Replace(match.Groups["unc"].Value, drive.Drive);
if (File.Exists(result) || Directory.Exists(result))
return result;
}
}
}
return uncSource;
}


#endregion

#region UncToDrive Class
/// <summary>
/// Class to store a combination of UNC path and Drive letter
/// </summary>
private class UncToDrive
{
private string _unc;
/// <summary>
/// Get the UNC path of this object
/// </summary>
public string Unc
{
get { return _unc; }
}

private string _drive;
/// <summary>
/// Get the drive letter for this object
/// </summary>
public string Drive
{
get { return _drive; }
}

private string _regex;
/// <summary>
/// Get the regex string for this object
/// </summary>
public string Regex
{
get { return _regex; }
}

/// <summary>
/// Creates an UncToDrive object.
/// </summary>
/// <param name="unc"></param>
/// <param name="drive"></param>
public UncToDrive(string unc, string drive)
{
_unc = unc;
//Create regex where both slash and backslash are allowed for \
_regex = String.Format("^( <unc>{0})", _unc.Replace(@"\", @"(/|\\)").Replace("$", @"\$"));
_drive = drive;
}
}

#endregion
}
}