关于c#:检查目录在网络驱动器上是否存在

Check if directory exists on Network Drive

我试图检测目录是否存在,但是在这种特殊情况下,我的目录是网络位置。
我使用了VB.NET的My.Computer.FileSystem.DirectoryExists(PATH)和更通用的System.IO.Directory.Exists(PATH),在两种情况下,系统响应均为false。
我检查了PATH是否存在,可以在MyComputer文件夹中查看它。
如果我调试程序,并观察My.Computer.FileSystem.Drives变量,则网络位置不会出现在该列表中。

更新:我检查并在Windows XP中响应为True,但在Windows 7中则不是。

UPDATE2:我测试了两个建议的解决方案,但仍然存在相同的问题,在下图中,您会看到我可以使用资源管理器进行访问,但是我的程序不能。
GetUNCPath函数返回有效路径(无错误),但是Directory.Exists stil返回false。

我也尝试使用UNC路径" \\ Server \ Images";同样的结果。

enter image description here

UPDATE3:如果无法链接到网络驱动器,如何直接链接到UNC路径?我发现,如果我在正常模式下运行VS,它可以工作,但是我的软件必须在管理员模式下运行。因此,有没有办法以管理员身份检查网络目录的存在?


如果打开了UAC,则映射的网络驱动器在映射它们的会话中仅"默认"存在:正常或提升。如果从资源管理器映射网络驱动器,然后以admin身份运行VS,则该驱动器将不存在。

您需要启用MS所谓的"链接的连接":
HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Windows \ CurrentVersion \ Policies \ System:EnableLinkedConnections(REG_DWORD)= 0x1

有关使用UAC进行"两次登录会话"的背景信息:http://support.microsoft.com/kb/937624/en-us


当您使用System.IO.Directory.Exists时,它只会让您知道它找不到目录,但这可能是因为该目录实际上不存在,或者是因为用户对该目录没有足够的访问权限。

为了解决此问题,我们在Directory.Exists无法获得缺少目录的真正原因后添加了辅助测试,并将其包装到一个全局方法中,该方法代替了标准的Directory.Exists方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
''' <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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
        }
    }

要使用它,请传递网络文件夹路径,转换为UNC文件夹路径,然后查看该文件夹是否存在:

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

编辑:

当我查看网络驱动器时,我看到了您的第二次编辑和唯一的区别(在Windows7中),我看到了"计算机">"图像"(\\ xyzServer)。您的PC名称是Equipo吗?那支球队是西班牙人吗?那是你的电脑吗?我试图重现您的问题,但对我有用:

enter image description here


除此之外,我需要对可能列出的网络共享进行"存在"检查,但是该帐户没有访问权限,因此Directory.Exists将返回False。

发布的各种解决方案都不适用于我,因此这是我自己的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static bool DirectoryVisible(string path)
{
    try
    {
        Directory.GetAccessControl(path);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return true;
    }
    catch
    {
        return false;
    }
}