【问题标题】:Check if directory exists on Network Drive检查网络驱动器上是否存在目录
【发布时间】:2013-07-04 13:55:28
【问题描述】:

我正在尝试检测该目录是否存在,但在这种特殊情况下,我的目录是一个网络位置。 我使用了 VB.NET 的My.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,它可以工作,但我的软件必须在管理员模式下运行。那么,有没有办法以管理员身份检查网络目录是否存在呢?

【问题讨论】:

  • 听起来可能是 UAC 问题。您是否以管理员身份运行程序?
  • 是的,我以管理员权限运行 Visual Studio。
  • 我了解到您确实以预期的格式引入了路径,即:\\server_name\folder\file.this
  • 不,我映射一个网络驱动器,所以我传递给函数的路径是 Z:\\FolderName
  • 啊,好的。那我不知道怎么了。在硬盘驱动器或本地网络中使用 System.IO 定位文件/文件夹时,我从来没有遇到过任何问题。

标签: c# windows vb.net .net-4.0


【解决方案1】:

如果打开 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

【讨论】:

  • 我在普通帐户下运行 VS,它运行良好,我在 HKEY_LOCAL_MACHINE 上创建了 EnableLinkedConnections 键,但是当我在管理员模式下运行 VS 时仍然出现错误。
  • 等等,我在网上看,他们说我必须重新启动计算机,所以我会先检查一下。
  • @Natalia 正确 - 修改注册表后应随时重新启动系统以确保更改发生。这解决了问题吗?
  • 我们在访问 '\\computername\folder' 时遇到了问题,但在应用此注册表设置后(正如它在 Internet 上所说,重新启动计算机)一切正常。非常感谢!
【解决方案2】:

当您使用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

【讨论】:

  • @Natalia:我唯一能想到的是应用程序没有像您认为的用户那样运行,因此没有获得映射的驱动器。您可以通过添加以下代码来查看 exe 的运行身份:Debug.WriteLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name)
  • 我写了那行代码,运行应用程序的用户就是我的用户。此用户是管理员。我认为这不是问题。
  • 我也有同样的问题,问题来自vs以不同的账户运行。以管理员身份运行不同于以管理员组中的帐户运行。很容易检查:尝试以普通帐户运行visual studio,而不是管理员。
  • @Qwench 我在普通帐户中运行 VS,它运行良好,但我需要在管理员模式下运行我的代码。那么,我该如何解决呢?
  • @Natalia:如果您在管理员模式下运行您的应用程序并使用您正在运行的机器的本地管理员,则它将无法访问网络驱动器。为了实现您的目标,您必须以网络用户身份运行,该用户既可以访问网络驱动器,又可以在本地计算机上拥有管理员权限。假设有足够的权限,您可以将网络用户添加到本地计算机的管理员组以满足此需求。
【解决方案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;
        }
    }

要使用它,传入一个Network文件夹路径,转换成UNC文件夹路径,看看文件夹是否存在:

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

编辑:

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

【讨论】:

  • 是的,我的计算机名称是“Equipo”,我来自阿根廷。我不知道为什么我的 Visual Studio 无法识别我的 Windows 7 上的网络驱动器。这个问题让我发疯。
【解决方案4】:

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

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

public static bool DirectoryVisible(string path)
{
    try
    {
        Directory.GetAccessControl(path);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return true;
    }
    catch
    {
        return false;
    }
}

【讨论】:

    猜你喜欢
    • 2015-04-01
    • 2015-01-30
    • 2017-09-09
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 2011-02-14
    相关资源
    最近更新 更多