Occasionally you might have the need to convert a mapped drive letter to a UNC or network path. For example, a drive letter such as “Z” might be mapped to a network share:
In this example, the “Z” drive is mapped to a “Personal” folder on a server named “Home”.
If you want to store for example a UNC path to a file rather than a drive letter, you’ll need to convert the “Z” drive to the corresponding UNC root path. Here’s the C# code I wrote to do this:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.IO; namespace WiredPrairie.Samples { public static class Pathing { [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int WNetGetConnection( [MarshalAs(UnmanagedType.LPTStr)] string localName, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder remoteName, ref int length); /// <summary> /// Given a path, returns the UNC path or the original. (No exceptions /// are raised by this function directly). For example, "P:\2008-02-29" /// might return: "\\networkserver\Shares\Photos\2008-02-09" /// </summary> /// <param name="originalPath">The path to convert to a UNC Path</param> /// <returns>A UNC path. If a network drive letter is specified, the /// drive letter is converted to a UNC or network path. If the /// originalPath cannot be converted, it is returned unchanged.</returns> public static string GetUNCPath(string originalPath) { StringBuilder sb = new StringBuilder(512); int size = sb.Capacity; // look for the {LETTER}: combination ... if (originalPath.Length > 2 && originalPath[1] == ':') { // don't use char.IsLetter here - as that can be misleading // the only valid drive letters are a-z && A-Z. char c = originalPath[0]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { int error = WNetGetConnection(originalPath.Substring(0, 2), sb, ref size); if (error == 0) { DirectoryInfo dir = new DirectoryInfo(originalPath); string path = Path.GetFullPath(originalPath) .Substring(Path.GetPathRoot(originalPath).Length); return Path.Combine(sb.ToString().TrimEnd(), path); } } } return originalPath; } } }
All of the magic takes place in a Windows API function call, WNetGetConnection.
I’m using this function so that I can verify that given two file names, I can be assured that they are pointing to the same physical location. (Is “Z:\Backups\Backup1.zip” the same as “\\home\Personal\Backups\Backup1.zip”).
Actually… there were quite a few problems with the above code. It needed some serious editing just to get it to compile, I’m not sure if it works yet though. I hope I did it right.
Sorry — it looks like some of the characters were stripped when I posted it for some reason.
I’ve reposted it — everything should be back to normal.
Ah, much better!
Thanks for the article. It was exactly what I was looking for! :)
Really Cool.. This is exactly what i was looking for.
This is working only when i run the code through vs 2008,while acessing the page in IE with nt login this is not working.
I tested the code with C# 2008 and it works great!
Thanks for the article!
worked a treat! thanks for that
Thank You so much, It is wonderful
wonderful!!! worked like a charm.
your article was extremely helpful. Thanks!
Sweet, exactly what I was looking for.
Thanks for posting this it saved a bunch of my time.
Perfect – exactly what I was looking for. Thank you and keep it up.
Really Cool.. This is exactly what i was looking for.
Wouldn’t it be easier to use the WNetGetUniversalName API?
Should use this:
IO.Path.VolumeSeparatorChar
instead of a hard-coded “:”c
While that’s true it would be more correct, on Windows, it’s hard coded in the .NET 4.0 framework to be a “:”. :)
(And this call wouldn’t make sense on anything but Windows with a mapped drive letter, so portability really isn’t an issue).