30

The easiest way to check if a path is an UNC path is of course to check if the first character in the full path is a letter or backslash. Is this a good solution or could there be problems with it?

My specific problem is that I want to create an System.IO.DriveInfo-object if there is a drive letter in the path.

David Eliason
  • 301
  • 1
  • 3
  • 7

5 Answers5

29

Try this extension method:

public static bool IsUncPath(this string path)
{
    return Uri.TryCreate(path, UriKind.Absolute, out Uri uri) && uri.IsUnc;
}
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 5
    The DriveInfo object cannot be used for UNC paths. But if I change it to be an extension to DirectoryInfo, and use the FullName instead of Name, it seems to work fine. – David Eliason Feb 06 '09 at 16:18
  • 1
    Is there a reason for not using `DirectoryInfo.DriveType == DriveType.Network` instead of `Uri.TryCreate`? – larsmoa Sep 19 '13 at 08:18
  • 1
    The reason not to use DirectoryInfo.DriveType is that such a property exists in DriveInfo and DriveInfo cannot be initialized with a UNC path – Eugenio Miró Mar 13 '18 at 20:55
20

Since a path without two backslashes in the first and second positions is, by definiton, not a UNC path, this is a safe way to make this determination.

A path with a drive letter in the first position (c:) is a rooted local path.

A path without either of this things (myfolder\blah) is a relative local path. This includes a path with only a single slash (\myfolder\blah).

TheSmurf
  • 15,337
  • 3
  • 40
  • 48
  • You should check at least for "\\" to start the path, as "\this\is\not\a\unc\path" (it's not a particularly good thing to have in the path, but it's not a UNC regardless). – Michael Burr Feb 06 '09 at 16:08
  • 1
    what about localized systems where the path separator is different? e.g. ¥ in Japanese systems – Sheng Jiang 蒋晟 May 03 '11 at 21:28
  • 1
    See the answer to this question: http://stackoverflow.com/questions/7314606/get-directory-separator-char-on-windows-etc – TheSmurf Jul 24 '12 at 19:30
  • 1
    Mapped directories and symlinks can also point to UNC paths and therefore may not be local – Edd Oct 10 '13 at 11:00
  • @TheSmurf your referenced question is about `C`, @ShengJiang蒋晟 in .NET we have `System.IO.Path.DirectorySeparatorChar` – Nicolas Jan 10 '19 at 14:45
14

The most accurate approach is going to be using some interop code from the shlwapi.dll

[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
[ResourceExposure(ResourceScope.None)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
internal static extern bool PathIsUNC([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);

You would then call it like this:

    /// <summary>
    /// Determines if the string is a valid Universal Naming Convention (UNC)
    /// for a server and share path.
    /// </summary>
    /// <param name="path">The path to be tested.</param>
    /// <returns><see langword="true"/> if the path is a valid UNC path; 
    /// otherwise, <see langword="false"/>.</returns>
    public static bool IsUncPath(string path)
    {
        return PathIsUNC(path);
    }

@JaredPar has the best answer using purely managed code.

Community
  • 1
  • 1
Scott Dorman
  • 42,236
  • 12
  • 79
  • 110
5

This is my version:

public static bool IsUnc(string path)
{
    string root = Path.GetPathRoot(path);

    // Check if root starts with "\\", clearly an UNC
    if (root.StartsWith(@"\\"))
    return true;

    // Check if the drive is a network drive
    DriveInfo drive = new DriveInfo(root);
    if (drive.DriveType == DriveType.Network)
    return true;

    return false;
}

The advantage of this version over @JaredPars version is that this supports any path, not just DriveInfo.

larsmoa
  • 12,604
  • 8
  • 62
  • 85
5

One trick I've found is to use dInfo.FullName.StartsWith(String.Empty.PadLeft(2, IO.Path.DirectorySeparatorChar)) where dInfo is a DirectoryInfo object - if that check returns True then it's a UNC path, otherwise it's a local path

DC Bane
  • 51
  • 1
  • 2