UrlCreateFromPath来救援! 好吧,并非完全,因为它不支持扩展和UNC路径格式,但这不是很难克服:
public static Uri FileUrlFromPath(string path)
{
const string prefix = @"\\";
const string extended = @"\\?\";
const string extendedUnc = @"\\?\UNC\";
const string device = @"\\.\";
const StringComparison comp = StringComparison.Ordinal;
if(path.StartsWith(extendedUnc, comp))
{
path = prefix+path.Substring(extendedUnc.Length);
}else if(path.StartsWith(extended, comp))
{
path = prefix+path.Substring(extended.Length);
}else if(path.StartsWith(device, comp))
{
path = prefix+path.Substring(device.Length);
}
int len = 1;
var buffer = new StringBuilder(len);
int result = UrlCreateFromPath(path, buffer, ref len, 0);
if(len == 1) Marshal.ThrowExceptionForHR(result);
buffer.EnsureCapacity(len);
result = UrlCreateFromPath(path, buffer, ref len, 0);
if(result == 1) throw new ArgumentException("Argument is not a valid path.", "path");
Marshal.ThrowExceptionForHR(result);
return new Uri(buffer.ToString());
}
[DllImport("shlwapi.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int UrlCreateFromPath(string path, StringBuilder url, ref int urlLength, int reserved);
如果路径以特殊前缀开头,则会删除它。 虽然文档没有提到它,但即使缓冲区较小,函数也会输出URL的长度,所以我首先获取长度,然后分配缓冲区。
我有一个非常有趣的观察是,当“\\ device \ path”被正确转换为“[file:// device / path”时,]具体地说“\\ localhost \ path”被转换为“[file://” /路径”。]
WinApi函数设法对特殊字符进行编码,但不像Uri construtor那样保留未编码的Unicode特定字符。 在这种情况下,AbsoluteUri包含正确编码的URL,而OriginalString可用于保留Unicode字符。