Search code examples
c#pathrelative-path

How to get the relative of a folder from two different projects


I have two projects and one shared library that loads images from this folder: "C:/MainProject/Project1/Images/"

Project1's folder: "C:/MainProject/Project1/Files/Bin/x86/Debug" (where there is project1.exe)

Project2's folder: "C:/MainProject/Project2/Bin/x86/Debug" (where there is project2.exe)

When I call the shared library function to load images, I need to obtain the relative path of "Images" folder, because I will call the function from either project1 or project2. Also I will move my MainProject in other computers, so I can't use absolute paths.

From Project1 I would do:

Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.Parent.FullName + @"\Images";

From Project2 I would do:

Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.Parent.FullName + @"Project1\Images";

How can I obtain the relative path by both projects folders?


Solution

  • You probably want to test this code a little and make it more robust, but it should work as long as you don't pass it UNC addresses. It works by splitting the paths into directory names and comparing them left to right. Then a relative path is built.

        public static string GetRelativePath(string sourcePath, string targetPath)
        {
            if (!Path.IsPathRooted(sourcePath)) throw new ArgumentException("Path must be absolute", "sourcePath");
            if (!Path.IsPathRooted(targetPath)) throw new ArgumentException("Path must be absolute", "targetPath");
    
            string[] sourceParts = sourcePath.Split(Path.DirectorySeparatorChar);
            string[] targetParts = targetPath.Split(Path.DirectorySeparatorChar);
    
            int n;
            for (n = 0; n < Math.Min(sourceParts.Length, targetParts.Length); n++ )
            {
                if (!string.Equals(sourceParts[n], targetParts[n], StringComparison.CurrentCultureIgnoreCase))
                {
                    break;
                }
            }
    
            if (n == 0) throw new ApplicationException("Files must be on the same volume");
            string relativePath = new string('.', sourceParts.Length - n).Replace(".", ".." + Path.DirectorySeparatorChar);
            if (n <= targetParts.Length)
            {
                relativePath += string.Join(Path.DirectorySeparatorChar.ToString(), targetParts.Skip(n).ToArray());
            }
    
            return string.IsNullOrWhiteSpace(relativePath) ? "." : relativePath;
        }
    

    Instead of using Directory.GetCurrentDirectory, consider using Path.GetDirectory(Process.GetCurrentProcess().MainModule.FileName). Your current directory might be different from your exe file which will break your code. MainModule.FileName points directly to the location of your exe file.