将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路径获取本地路径
文章中的代码。此函数将采用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,但也有一些例子,然后就像上面一样,你需要匹配共享名。