在 C# 中将 UNC 路径转换为本地路径

Posted

技术标签:

【中文标题】在 C# 中将 UNC 路径转换为本地路径【英文标题】:Convert UNC path to local path in C# 【发布时间】:2014-05-22 02:55:45 【问题描述】:

有没有办法从 UNC 路径获取本地路径?

例如:\\server7\hello.jpg 应该给我 D:\attachments\hello.jpg

在应用 Windows 文件名和完整路径长度限制后,我正在尝试将附件保存到 UNC 路径。在这里,我通过以 UNC 路径长度为参考来应用这些限制。但是本地路径长度比 UNC 路径长,我认为因此我得到了以下异常。

System.IO.PathTooLongException 发生 HResult=-2147024690 Message=指定的路径、文件名或两者都太长。完全 限定文件名必须少于 260 个字符,并且 目录名称必须少于 248 个字符。来源=mscorlib 堆栈跟踪: 在 System.IO.PathHelper.GetFullPathName() 在 System.IO.Path.NormalizePath(字符串路径,布尔 fullCheck,Int32 maxPathLength,布尔 expandShortPaths) 在 System.IO.Path.NormalizePath(字符串路径,布尔 fullCheck,Int32 maxPathLength) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize,FileOptions 选项,SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean 检查主机) 在 System.IO.FileStream..ctor(字符串路径、FileMode 模式、FileAccess 访问、FileShare 共享、Int32 bufferSize、FileOptions 选项,字符串 msgPath,布尔 bFromProxy) 在 System.IO.FileStream..ctor(字符串路径,FileMode 模式) 在 Presensoft.JournalEmailVerification.EmailVerification.DownloadFailedAttachments(EmailMessage msg, JournalEmail journalEmail) 在 D:\Source\ProductionReleases\Release_8.0.7.0\Email 存档\Presensoft.JournalEmailVerification\EmailVerification.cs:line 630 内部异常:

【问题讨论】:

检查***.com/questions/2091126/… 【参考方案1】:

看看这篇博文:Get local path from UNC path

文章中的代码。此函数将采用 UNC 路径(例如 \server\share 或 \server\c$\folder 并返回本地路径(例如 c:\share 或 c:\folder)。

using System.Management;

public static string GetPath(string uncPath)

  try
  
    // remove the "\\" from the UNC path and split the path
    uncPath = uncPath.Replace(@"\\", "");
    string[] uncParts = uncPath.Split(new char[] '\\', StringSplitOptions.RemoveEmptyEntries);
    if (uncParts.Length < 2)
      return "[UNRESOLVED UNC PATH: " + uncPath + "]";
    // Get a connection to the server as found in the UNC path
    ManagementScope scope = new ManagementScope(@"\\" + uncParts[0] + @"\root\cimv2");
    // Query the server for the share name
    SelectQuery query = new SelectQuery("Select * From Win32_Share Where Name = '" + uncParts[1] + "'");
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);

    // Get the path
    string path = string.Empty;
    foreach (ManagementObject obj in searcher.Get())
    
      path = obj["path"].ToString();
    

    // Append any additional folders to the local path name
    if (uncParts.Length > 2)
    
      for (int i = 2; i < uncParts.Length; i++)
        path = path.EndsWith(@"\") ? path + uncParts[i] : path + @"\" + uncParts[i];
    

    return path;
  
  catch (Exception ex)
  
    return "[ERROR RESOLVING UNC PATH: " + uncPath + ": "+ex.Message+"]";
  

该函数使用 ManagementObjectSearcher 在网络服务器上搜索共享。如果您没有对该服务器的读取权限,则需要使用不同的凭据登录。将 ManagementScope 的行替换为以下行:

ConnectionOptions options = new ConnectionOptions();
options.Username = "username";
options.Password = "password";
ManagementScope scope = new ManagementScope(@"\\" + uncParts[0] + @"\root\cimv2", options);

【讨论】:

【参考方案2】:

这也适用于大多数情况。比系统管理简单一点。

public static string MakeDiskRootFromUncRoot(string astrPath)

    string strPath = astrPath;
    if (strPath.StartsWith("\\\\"))
    
        strPath = strPath.Substring(2);
        int ind = strPath.IndexOf('$');
        if(ind>1 && strPath.Length >= 2)
        
            string driveLetter = strPath.Substring(ind - 1,1);
            strPath = strPath.Substring(ind + 1);
            strPath = driveLetter + ":" + strPath;
        

    
    return strPath;

【讨论】:

如果 UNC 路径不包含 '$',则当 UNC 的格式为 \\host\dir1\dir1\dir3\ 时不起作用,并且当 UNC 路径为格式为 \\host\driveLetter\dir\【参考方案3】:

我自己也需要这个,尽管是出于 DirQuota 设置的目的。由于我的代码将以服务器管理员身份运行,因此 WMI 查询示例最简单,只需将其重写为更具可读性:

public static string ShareToLocalPath(string sharePath)

    try
    
        var regex = new Regex(@"\\\\([^\\]*)\\([^\\]*)(\\.*)?");
        var match = regex.Match(sharePath);
        if (!match.Success) return "";

        var shareHost = match.Groups[1].Value;
        var shareName = match.Groups[2].Value;
        var shareDirs = match.Groups[3].Value;

        var scope = new ManagementScope(@"\\" + shareHost + @"\root\cimv2");
        var query = new SelectQuery("SELECT * FROM Win32_Share WHERE name = '" + shareName + "'");

        using (var searcher = new ManagementObjectSearcher(scope, query))
        
            var result = searcher.Get();
            foreach (var item in result) return item["path"].ToString() + shareDirs;
        

        return "";
    
    catch (Exception)
    
        return "";
    

在幕后,这是读取服务器注册表项:

'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanServer\Shares'

如果您需要在目标服务器上转换没有管理员权限的路径,请查看 Netapi32.dll 的“NetShareEnum”功能。虽然您通常看不到它,但隐藏的共享和本地路径会广播给普通用户。代码稍微复杂一点,因为它需要 DllImport,但有一些示例,然后就像上面一样,您需要匹配共享名称。

【讨论】:

以上是关于在 C# 中将 UNC 路径转换为本地路径的主要内容,如果未能解决你的问题,请参考以下文章

本地计算机上文件夹的 UNC 路径

从 UNC 路径获取 DFS 服务器名称和本地路径

Windows 7 - 无网络 - 我需要在本地伪造 UNC 路径以进行开发/测试吗?

无法访问 Powershell 远程会话中的 UNC 路径

获取本地网络服务器上所有 UNC 共享文件夹的列表

在云中创建 Blob 存储 UNC 路径