簡體   English   中英

在C#中將UNC路徑轉換為本地路徑

[英]Convert UNC path to local path in C#

有沒有辦法從UNC路徑獲取本地路徑?

例如:\\\\ server7 \\ hello.jpg應該給我D:\\ attachments \\ hello.jpg

我試圖在應用Windows文件名和完整路徑長度限制后將附件保存到UNC路徑。 在這里,我以UNC路徑長度為參考來應用限制。 但是本地路徑的長度比UNC路徑長,我想因此而得到以下異常。

發生System.IO.PathTooLongException HResult = -2147024690
Message =指定的路徑,文件名或兩者都太長。 完全限定的文件名必須少於260個字符,目錄名稱必須少於248個字符。 來源= mscorlib
StackTrace:位於System.IO.Path.NormalizePath(String path,Boolean fullCheck,Int32 maxPathLength,Boolean expandShortPaths)位於System.IO.Path.NormalizePath(String path,Boolean fullCheck,Int32 maxPathLength)中的System.IO.PathHelper.GetFullPathName() )at System.IO.FileStream.Init(字符串路徑,FileMode模式,FileAccess訪問,Int32權限,布爾useRights,FileShare共享,Int32 bufferSize,FileOptions選項,SECURITY_ATTRIBUTES secAttrs,字符串msgPath,布爾bFromProxy,布爾useLongPath,布爾checkHost) System.IO.FileStream..ctor(字符串路徑,FileMode模式,FileAccess訪問,FileShare共享,Int32 bufferSize,FileOptions選項,String msgPath,布爾bFromProxy)在System.IO.FileStream..ctor(字符串路徑,FileMode模式)在D:\\ Source \\ ProductionReleases \\ Release_8.0.7.0 \\ Email Archiving \\ Presensoft.JournalEmailVerification \\ EmailVerification.cs:lin中的Presensoft.JournalEmailVerification.EmailVerification.DownloadFailedAttachments(EmailMessage msg,JournalEmail journalEmail) e 630 InnerException:

看一下這篇博客文章: 從UNC路徑獲取本地路徑

文章中的代碼。 此函數將采用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);

這在大多數情況下也適用。 比系統管理簡單一點。

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'

如果需要在目標服務器上不使用admin轉換路徑,請簽出Netapi32.dll的“ NetShareEnum”功能。 盡管您通常看不到它,但是隱藏的共享和本地路徑會廣播給普通用戶。 該代碼稍微復雜一點,因為它需要DllImport,但是有一些示例,然后像上面一樣,您需要匹配共享名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM