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

本文关键字:路径 UNC 转换 | 更新日期: 2023-09-27 17:57:26

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

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

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

发生System.IO.PathTooLongException HResult=-2147024690
消息=指定的路径、文件名或两者都太长。完全限定的文件名必须少于260个字符,并且目录名必须少于248个字符。来源=mscorlib
StackTrace:位于System.IO.PathHelper.GetFullPathName()位于System.IO.Path.NormalizePath(字符串路径,布尔值fullCheck,Int32 maxPathLength,布尔值expandShortPaths)位于System.IO.Path.NormalizePath(字符串路径,布尔值fullCheck,Int32 maxPathLength)在System.IO.FileStream.Init(字符串路径,FileMode模式,FileAccess访问,Int32权限,布尔使用权限,FileShare共享,Int32缓冲区大小,文件选项,SECURITY_ATTRIBUTES secAttrs,字符串msgPath,布尔bFromProxy,布尔useLongPath,布尔checkHost)在System.IO.FileStream.ctor(字符串路径、FileMode模式、FileAccess访问、FileShare共享、Int32缓冲区大小、FileOptions选项,字符串msgPath,布尔bFromProxy)在System.IO.FileStream.ctor(字符串路径,FileMode模式)在Presensoft.JournalEmailVerification.EmailVerification.DownloadFailedAttachments(EmailMessagemsg,日志电子邮件日志电子邮件)D: ''Source''ProductionReleases''Release_8.0.7.0''电子邮件存档'' Presensoft.JournalEmailVerification''电子邮件验证.cs:line630内部异常:

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

看看这篇博客文章:从UNC路径获取本地路径

文章中的代码。此函数将采用UNC路径(例如''server''share或''server''c$''文件夹),并返回本地路径(例如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);

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

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

我自己也需要这个,尽管是为了设置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,但也有一些例子,然后就像上面一样,你需要匹配共享名。