Check if directory exists on Network Drive

37,955

Solution 1

If UAC is turned on, mapped network drives only exist "by default" in the session they are mapped: Normal or elevated. If you map a network drive from explorer, then run VS as admin, the drive will not be there.

You need to enable what MS calls "linked connections": HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System: EnableLinkedConnections (REG_DWORD) = 0x1

Background Information about "two logon sessions" with UAC: http://support.microsoft.com/kb/937624/en-us

Solution 2

When you use System.IO.Directory.Exists, it only lets you know that it couldn't find the directory, but this could be because the directory doesn't actually exist or because the user doesn't have sufficient access rights to the directory.

In order to resolve this, we add a secondary test after Directory.Exists fails to obtain the real reason for the directory's absence and we have wrapped this into a global method that is used in place of the standard Directory.Exists method:

''' <summary>
''' This method tests to ensure that a directory actually does exist. If it does not, the reason for its 
''' absence will attempt to be determined and returned. The standard Directory.Exists does not raise 
''' any exceptions, which makes it impossible to determine why the request fails.
''' </summary>
''' <param name="sDirectory"></param>
''' <param name="sError"></param>
''' <param name="fActuallyDoesntExist">This is set to true when an error is not encountered while trying to verify the directory's existence. This means that 
''' we have access to the location the directory is supposed to be, but it simply doesn't exist. If this is false and the directory doesn't exist, then 
''' this means that an error, such as a security error, was encountered while trying to verify the directory's existence.</param>
Public Function DirectoryExists(ByVal sDirectory As String, ByRef sError As String, Optional ByRef fActuallyDoesntExist As Boolean = False) As Boolean
    ' Exceptions are partially handled by the caller

    If Not IO.Directory.Exists(sDirectory) Then
        Try
            Dim dtCreated As Date

            ' Attempt to retrieve the creation time for the directory. 
            ' This will usually throw an exception with the complaint (such as user logon failure)
            dtCreated = Directory.GetCreationTime(sDirectory)

            ' Indicate that the directory really doesn't exist
            fActuallyDoesntExist = True

            ' If an exception does not get thrown, the time that is returned is actually for the parent directory, 
            ' so there is no issue accessing the folder, it just doesn't exist.
            sError = "The directory does not exist"
        Catch theException As Exception
            ' Let the caller know the error that was encountered
            sError = theException.Message
        End Try

        Return False
    Else
        Return True
    End If
End Function

Solution 3

public static class MappedDriveResolver
    {
        [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;

            // 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;
        }
    }

To use it, pass in a Network folder path, convert to UNC folder path and see if the folder exists:

File.Exists(MappedDriveResolver.GetUNCPath(filePath));

Edit:

I saw your second edit and the only difference (in my Windows7) when I view a network drive I see Computer > Images (\\xyzServer). Is your PC's name Equipo? is that team in spanish? is that your PC? I tried to reproduce your problem but it works for me:

enter image description here

Solution 4

Adding to this, I needed to do an 'Exists' check on network shares that could listed, but the account did not have permission to access, so Directory.Exists would return False.

Various solutions posted did not work for me, so here is my own:

public static bool DirectoryVisible(string path)
{
    try
    {
        Directory.GetAccessControl(path);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return true;
    }
    catch
    {
        return false;
    }
}
Share:
37,955
Natalia
Author by

Natalia

Updated on July 12, 2022

Comments

  • Natalia
    Natalia almost 2 years

    I'm trying to detect if the directory exists, but in this particular situation my directory is a network location. I used VB.NET's My.Computer.FileSystem.DirectoryExists(PATH) and the more general System.IO.Directory.Exists(PATH), and in both cases, the system response is false. I checked and the PATH exists, I can view it in MyComputer Folder. If I debug the program, and watch the My.Computer.FileSystem.Drives variable, the network location does not appear in that list.

    UPDATE: I checked and in Windows XP the Response is True, but not in Windows 7.

    UPDATE2: I tested both proposed solutions but I still have the same problem, on the image below you will see that I can access using Explorer but my program cannot. The GetUNCPath function returns a valid path (no errors), but Directory.Exists stil returns false.

    I also tried with the UNC path "\\Server\Images"; same result.

    enter image description here

    UPDATE3: If I cannot link with a network drive, how can I link to UNC path directly?. I discovered that if i run VS in normal mode, it works, but my software must run in administrator mode. So, there is any way to check the existence of a network directory as administrator?