24

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

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

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

我还尝试使用 UNC 路径“\\Server\Images”;同样的结果。

在此处输入图像描述

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

4

4 回答 4

17

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

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

关于 UAC 的“两次登录会话”的背景信息:http: //support.microsoft.com/kb/937624/en-us

于 2013-07-17T15:40:00.613 回答
8

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

为了解决这个问题,我们在Directory.Exists未能获得目录不存在的真正原因后添加了一个辅助测试,我们将其包装到一个全局方法中,用于代替标准Directory.Exists方法:

''' <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
于 2013-07-04T17:10:12.413 回答
5
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 文件夹路径并查看该文件夹是否存在:

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

编辑:

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

在此处输入图像描述

于 2013-07-05T05:08:06.790 回答
2

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

发布的各种解决方案对我不起作用,所以这是我自己的:

public static bool DirectoryVisible(string path)
{
    try
    {
        Directory.GetAccessControl(path);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return true;
    }
    catch
    {
        return false;
    }
}
于 2014-01-27T15:45:15.503 回答