• Skip to content
  • Skip to primary sidebar

Technical Notes Of
Ehi Kioya

Technical Notes Of Ehi Kioya

  • Blog
  • Shop
  • Subscribe
  • About
  • Contact
MENUMENU
  • Blog Home
  • AWS, Azure, Cloud
  • Backend (Server-Side)
  • Frontend (Client-Side)
  • SharePoint
  • Tools & Resources
    • CM/IN Ruler
    • URL Decoder
    • Text Hasher
  • Linux & Servers
  • Zero Code Tech
  • WordPress
  • Musings
  • More
    Categories
    • Cloud
    • Server-Side
    • Front-End
    • SharePoint
    • Tools
    • Linux
    • Zero Code
    • WordPress
    • Musings
Home » Backend (Server-Side) » Get Network Path Of Mapped Drive With C#

Get Network Path Of Mapped Drive With C#

By Ehi Kioya Leave a Comment

There are a number of resources out there that attempt to explain how to get the network path of a mapped drive letter or path. However, I found most of them to be incomplete and/or full of errors.

For example, my attempts to do this with the ManagementObject and ManagementPath classes always failed with an exception like:
The type initializer for ‘System.Management.ManagementPath’ threw an exception. This might have been because I was working from a VM or maybe some other OS issue.

The solution I found that always worked across multiple environments involved the use of PInvoke and a dll import. True, it would be better if this could be done reliably with the .NET framework without needing to drill down into the Windows API, but until I find a better solution (or someone points out a better way in the comments here), I’ll be documenting this for others who might need it and for future reference.

This method accepts an absolute path (which could be on a mapped drive or on a local drive) and returns the equivalent UNC path (if exists).

If the absolute path cannot be converted to a UNC path, the absolute path is returned unchanged.

[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);
public static string GetUNCPath(string originalPath)
{
	StringBuilder sb = new StringBuilder(512);
	int size = sb.Capacity;

	if (originalPath.Length > 2 && originalPath[1] == ':')
	{
		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;
}

Remember to add a using statement for System.Runtime.InteropServices (contains the DllImportAttribute) and any other using statements the rest of your class may need.

Once we have imported mpr.dll the real work is done by calling a Windows API function.

Doing This Without PInvoke

This solution from Stackoverflow looks really interesting but sadly, didn’t work for me. I’m not sure yet why it’s failing on my environment and I intend to research on this later and possibly tweak the code to make it work.

It does not involve using PInvoke.

/// <summary>
/// A static class to help with resolving a mapped drive path to a UNC network path.
/// If a local drive path or a UNC network path are passed in, they will just be returned.
/// </summary>
/// <example>
/// using System;
/// using System.IO;
/// using System.Management;    // Reference System.Management.dll
///
/// // Example/Test paths, these will need to be adjusted to match your environment.
/// string[] paths = new string[] {
///     @"Z:\ShareName\Sub-Folder",
///     @"\\ACME-FILE\ShareName\Sub-Folder",
///     @"\\ACME.COM\ShareName\Sub-Folder", // DFS
///     @"C:\Temp",
///     @"\\localhost\c$\temp",
///     @"\\workstation\Temp",
///     @"Z:", // Mapped drive pointing to \\workstation\Temp
///     @"C:\",
///     @"Temp",
///     @".\Temp",
///     @"..\Temp",
///     "",
///     "    ",
///     null
/// };
///
/// foreach (var curPath in paths) {
///     try {
///         Console.WriteLine(string.Format("{0} = {1}",
///             curPath,
///             MappedDriveResolver.ResolveToUNC(curPath))
///         );
///     }
///     catch (Exception ex) {
///         Console.WriteLine(string.Format("{0} = {1}",
///             curPath,
///             ex.Message)
///         );
///     }
/// }
/// </example>
public static class MappedDriveResolver
{
    /// <summary>
    /// Resolves the given path to a full UNC path if the path is a mapped drive.
    /// Otherwise, just returns the given path.
    /// </summary>
    /// <param name="path">The path to resolve.</param>
    /// <returns></returns>
    public static string ResolveToUNC(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }

        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and ResolveToUNC does not support relative paths.",
                    path)
            );
        }

        // Is the path already in the UNC format?
        if (path.StartsWith(@"\\")) {
            return path;
        }

        string rootPath = ResolveToRootUNC(path);

        if (path.StartsWith(rootPath)) {
            return path; // Local drive, no resolving occurred
        }
        else {
            return path.Replace(GetDriveLetter(path), rootPath);
        }
    }

    /// <summary>
    /// Resolves the given path to a root UNC path if the path is a mapped drive.
    /// Otherwise, just returns the given path.
    /// </summary>
    /// <param name="path">The path to resolve.</param>
    /// <returns></returns>
    public static string ResolveToRootUNC(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }

        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and ResolveToRootUNC does not support relative paths.",
                path)
            );
        }

        if (path.StartsWith(@"\\")) {
            return Directory.GetDirectoryRoot(path);
        }

        // Get just the drive letter for WMI call
        string driveletter = GetDriveLetter(path);

        // Query WMI if the drive letter is a network drive, and if so the UNC path for it
        using (ManagementObject mo = new ManagementObject()) {
            mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", driveletter));

            DriveType driveType = (DriveType)((uint)mo["DriveType"]);
            string networkRoot = Convert.ToString(mo["ProviderName"]);

            if (driveType == DriveType.Network) {
                return networkRoot;
            }
            else {
                return driveletter + Path.DirectorySeparatorChar;
            }
        }
    }

    /// <summary>
    /// Checks if the given path is a network drive.
    /// </summary>
    /// <param name="path">The path to check.</param>
    /// <returns></returns>
    public static bool isNetworkDrive(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }

        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and ResolveToRootUNC does not support relative paths.",
                path)
            );
        }

        if (path.StartsWith(@"\\")) {
            return true;
        }

        // Get just the drive letter for WMI call
        string driveletter = GetDriveLetter(path);

        // Query WMI if the drive letter is a network drive
        using (ManagementObject mo = new ManagementObject()) {
            mo.Path = new ManagementPath(string.Format("Win32_LogicalDisk='{0}'", driveletter));
            DriveType driveType = (DriveType)((uint)mo["DriveType"]);
            return driveType == DriveType.Network;
        }
    }

    /// <summary>
    /// Given a path will extract just the drive letter with volume separator.
    /// </summary>
    /// <param name="path"></param>
    /// <returns>C:</returns>
    public static string GetDriveLetter(string path) {
        if (String.IsNullOrWhiteSpace(path)) {
            throw new ArgumentNullException("The path argument was null or whitespace.");
        }

        if (!Path.IsPathRooted(path)) {
            throw new ArgumentException(
                string.Format("The path '{0}' was not a rooted path and GetDriveLetter does not support relative paths.",
                path)
            );
        }

        if (path.StartsWith(@"\\")) {
            throw new ArgumentException("A UNC path was passed to GetDriveLetter");
        }

        return Directory.GetDirectoryRoot(path).Replace(Path.DirectorySeparatorChar.ToString(), "");
    }
}

If you want a pure framework based solution, you might want to try this method first and only use the PInvoke method as a last resort.

Found this article valuable? Want to show your appreciation? Here are some options:

  1. Spread the word! Below, you will find links to share this article on your favorite social media sites.
  2. Subscribe to my email notifications. That way, you'll never miss my updates.
  3. Buy something from my "shop". I sometimes get a commission.
  4. Contribute by adding a comment using the comments section below.
  5. Follow me on Twitter, LinkedIn, and Facebook.

Help me share this on . . .

  • Facebook
  • Twitter
  • LinkedIn
  • Reddit

Other Articles You May Like:

Filed Under: Backend (Server-Side), C# Tagged With: C#, MappedDrive, Programming, UNC

About Ehi Kioya

I am a Toronto-based Solutions Architect, Software Engineer, Cloud/DevOps Administrator, SharePoint Developer, Internet Entrepreneur, Electrical/Electronic Engineer, Independent Consultant, Consumer Products Geek, and Technology Blogger.

Niches, I think, are highly overrated. I'd much rather be a polymath. If I can (or can try), why not?!

I get satisfaction from solving problems programmatically and teaching people by example how to do tech stuff. When I can't find coding problems to challenge me, I get bored and create some.

I have written some more about myself here. You can also find me on Twitter, LinkedIn, and Facebook.

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Enter your email to get new content sent to your inbox daily!

Added! You'll hear from me shortly.

FROM   THE   SHOP

  • Ewok Dog Costume

    Ewok Dog Costume

    Transform your four-legged friend into an Ewok from the Forest Moon of Endor with this pet costume inspired by Star Wars. It features a shirt and headpiece with attached Ewok ears to create an ensemble look that is out of this world.

    $11.30
    Check it out
  • Talkboy Tape Recorder and Player (From Home Alone)

    Talkboy Tape Recorder and Player with Kevin McAllister As Seen in Home Alone II

    Piss off everyone you know and recreate classic scenes with this Talkboy Tape Recorder and Player. This collectible item is the very same one used by Kevin McAllister to annoy the shit out of everyone in Home Alone II.

    $189.00
    Check it out

READERS’ FEEDBACK

  • John on Different Ways To Take Screenshots In Windows 10I've been using Lightshot for a while now, works great. https://app.prntscr.com/en/download.html
  • Courtney on How To Set A Date Value In A SharePoint Designer WorkflowThis is a great guide on how to do this. Thanks!
  • Ezequiel Gioia on How To Shrink Amazon EBS Volumes (Root Or Non-Root)Hi Ehi, Great article! I was wondering if you will consider rsync an option for non-root volumes. I faced some shrink issues with big volumes (6 TiB),…
  • Andy Saw on Six Reasons Your WordPress Site Needs JetpackAnother 3 would be Jetpack includes in the CDN that will help speed up your loading of your WordPress website as static files like images are served f…
  • Howard Bash on Setting up a SharePoint 2016 dev farm in Azure – Part 4: SharePoint 2016 InstallationAll is working. I even added the alternate access mapping and can get site collection from outside the VM. Quick, question: I would like to add a coup…
  • Recently   Popular   Posts   &   Pages
  • Actual Size Online Ruler Actual Size Online Ruler
    I created this page to measure your screen resolution and produce an online ruler of actual size. It's powered with JavaScript and HTML5.
  • Get XML Document Nodes Recursively with C# Get XML Document Nodes Recursively with C#
    Here are two methods to get XML document nodes, child nodes and so on. The first method uses DOM. The second method uses LINQ to XML.
  • Round Robin DNS: How to Assign Multiple IP Addresses to One Domain Round Robin DNS: How to Assign Multiple IP Addresses to One Domain
    This article explains round robin DNS, load balancers, and how you set up round robin settings on your DNS server to handle high traffic.
  • Uploading files to a REST endpoint using C# Uploading files to a REST endpoint using C#
    Use this solution for uploading files to any REST endpoint using C#. It allows you to pass custom params that may be required by your API.
  • Get Network Path Of Mapped Drive With C# Get Network Path Of Mapped Drive With C#
    How to get the network path or UNC path of a mapped drive path programmatically. A PInvoke method and a .NET method is discussed.
  • How To Shrink Amazon EBS Volumes (Root Or Non-Root) How To Shrink Amazon EBS Volumes (Root Or Non-Root)
    In this article, I describe a technique to shrink Amazon EBS volumes. This is very useful if you ever mistakenly over-allocate your EBS.
  • WordPress Password Hash Generator WordPress Password Hash Generator
    With this WordPress Password Hash Generator, you can convert a password to its hash, and then set a new password directly in the database.
  • Blog
  • Shop
  • Subscribe
  • About
  • Contact

© 2019   ·   Ehi Kioya   ·   All Rights Reserved
Privacy Policy