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

时间:2014-04-09 05:27:52

标签: c# .net windows path

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

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

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

  

发生System.IO.PathTooLongException HResult = -2147024690
  消息=指定的路径,文件名或两者都太长。完全   限定文件名必须少于260个字符,并且   目录名称必须少于248个字符。来源= mscorlib程序
  堆栈跟踪:          在System.IO.PathHelper.GetFullPathName()          在System.IO.Path.NormalizePath(String path,Boolean fullCheck,Int32 maxPathLength,Boolean expandShortPaths)          在System.IO.Path.NormalizePath(String path,Boolean fullCheck,Int32 maxPathLength)          在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   checkHost)          在System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享,Int32 bufferSize,FileOptions   options,String msgPath,Boolean bFromProxy)          在System.IO.FileStream..ctor(字符串路径,FileMode模式)          在Presensoft.JournalEmailVerification.EmailVerification.DownloadFailedAttachments(EmailMessage)   msg,JournalEmail journalEmail)in   d:\来源\ ProductionReleases \ Release_8.0.7.0 \电子邮件   归档\ Presensoft.JournalEmailVerification \ EmailVerification.cs:行   630 InnerException:

3 个答案:

答案 0 :(得分:5)

请看一下这篇博客文章:Get local path from UNC path

文章的代码。此函数将采用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);

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

我自己也需要这个,尽管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 "";
    }
}

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

&#39; HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \服务\ LanmanServer \股份&#39;

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