PathCanonicalize equivalent in C#

前端 未结 3 1558
醉酒成梦
醉酒成梦 2021-01-12 00:07

What is the equivalent to PathCanonicalize in C#?

Use: I need to take a good guess whether two file paths refer to the same file (without disk access). My typical ap

3条回答
  •  广开言路
    2021-01-12 00:58

    3 solutions:

    Best case scenario, where you are 100% certain the calling process will have full access to the filesystem. CAVEAT: permission on a production box can be tricky

        public static string PathCombineAndCanonicalize1(string path1, string path2)
        {
            string combined = Path.Combine(path1, path2);
            combined = Path.GetFullPath(combined);
            return combined;
        }
    

    But, we're not always free. Often you need to do the string arithmetic without permission. There is a native call for this. CAVEAT: resorts to native call

        public static string PathCombineAndCanonicalize2(string path1, string path2)
        {
            string combined = Path.Combine(path1, path2);
            StringBuilder sb = new StringBuilder(Math.Max(260, 2 * combined.Length));
            PathCanonicalize(sb, combined);
            return sb.ToString();
        }
    
        [DllImport("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool PathCanonicalize([Out] StringBuilder dst, string src);
    

    A third strategy is to trick the CLR. Path.GetFullPath() works just fine on a fictitious path, so just make sure you're always giving it one. What you can do is to swap out the root with a phony UNC path, call GetFullPath(), and then swap the real one back in. CAVEAT: this may require a hard sell in code review

        public static string PathCombineAndCanonicalize3(string path1, string path2)
        {
            string originalRoot = string.Empty;
    
            if (Path.IsPathRooted(path1))
            {
                originalRoot = Path.GetPathRoot(path1);
                path1 = path1.Substring(originalRoot.Length);
            }
    
            string fakeRoot = @"\\thiscantbe\real\";
            string combined = Path.Combine(fakeRoot, path1, path2);
            combined = Path.GetFullPath(combined);
            combined = combined.Substring(fakeRoot.Length);
            combined = Path.Combine(originalRoot, combined);
            return combined;
        }
    

提交回复
热议问题