[editedit]
Ok, after a bit of contemplation, I did come up with an alternative, but it may not be palatable to all:
void Main()
{
var path1 = @"C:\Program Files\Internet Explorer\";
var path2 = @"C:\temp\";
var sb = new StringBuilder(1000);
PathRelativePathTo(sb, path1, 0, path2, 0);
sb.ToString().Dump();
}
/*
BOOL PathRelativePathTo(
_Out_ LPTSTR pszPath,
_In_ LPCTSTR pszFrom,
_In_ DWORD dwAttrFrom,
_In_ LPCTSTR pszTo,
_In_ DWORD dwAttrTo
);
*/
[DllImport("Shlwapi.dll")]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool PathRelativePathTo(
[Out] StringBuilder result,
[In] string pathFrom,
[In] int dwAttrFrom,
[In] string pathTo,
[In] int dwAttrTo);
Ooh, just had an idea - does this get you (more or less) what you need?
public string PathDiff(string path1, string path2)
{
var replace1 = path1.Replace(path2, string.Empty);
var replace2 = path2.Replace(path1, string.Empty);
return Path.IsPathRooted(replace1) ? replace2 : replace1;
}
Or possibly better:
public string PathDiff(string path1, string path2)
{
return path1.Length > path2.Length ?
path1.Replace(path2, string.Empty) :
path2.Replace(path1, string.Empty);
}
(edit: derp, hit submit too soon):
There's no built-in relative path helpers, unfortunately, but you've basically got it with what you've got, like so:
var path1 = @"C:\dev\src\release\Frontend\";
var path2 = @"C:\dev\src\";
var path1Uri = new Uri(path1);
var path2Uri = new Uri(path2);
var from1to2 = path1Uri.MakeRelativeUri(path2Uri).OriginalString;
var from2to1 = path2Uri.MakeRelativeUri(path1Uri).OriginalString;
Console.WriteLine("To go from {0} to {1}, you need to {2}", path1, path2, from1to2);
Console.WriteLine("To go from {0} to {1}, you need to {2}", path2, path1, from2to1);
Output:
To go from C:\dev\src\release\Frontend\ to C:\dev\src\, you need to ../../
To go from C:\dev\src\ to C:\dev\src\release\Frontend\, you need to release/Frontend/
Now, as for the slash differences "\" vs "/", if you wrap the end results in Path.GetFullPath
, it will auto-resolve the differences:
Console.WriteLine(Path.GetFullPath(Path.Combine(path1, from1to2)));
Console.WriteLine(Path.GetFullPath(Path.Combine(path2, from2to1)));
Output:
C:\dev\src\
C:\dev\src\release\Frontend\