[英]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.