The proper1 way to get the root folder of a C# project is to leverage the [CallerFilePath] attribute to obtain the full path name of a source file, and then subtract the filename plus extension from it, leaving you with the path to the project.
Here is how to actually do it:
In the root folder of your project, add file ProjectSourcePath.cs with the following content:
using System.Runtime.CompilerServices;
///<summary>
///Provides the full path to the source directory of the current project.<br/>
///(Only meaningful on the machine where this code was compiled.)<br/>
///From <a href="https://stackoverflow.com/a/66285728/773113"/>
///</summary>
internal static class ProjectSourcePath
{
private const string myRelativePath = nameof(ProjectSourcePath) + ".cs";
private static string? lazyValue;
///<summary>
///The full path to the source directory of the current project.
///</summary>
public static string Value => lazyValue ??= calculate();
private static string calculate( [CallerFilePath] string? path = null )
{
Assert( path!.EndsWith( myRelativePath, StringComparison.Ordinal ) );
return path.Substring( 0, path.Length - myRelativePath.Length );
}
}
Once you have the above, you can use it as follows:
string projectSourcePath = ProjectSourcePath.Value;
Notes:
The string? construct requires a non-ancient version of C# with #nullable enable; if you don't have it, then just remove the ? and the exclamation-mark in path!
The Assert() function is my own; you can replace it with your own, or omit it, if you like living your life dangerously.
1Proper as in: fool-proof; sure-fire; without presumptions; not being held together by shoestrings; not bound to work for some projects but fail for others; not likely to horribly break without a warning when you change unrelated things; etc.
Amendment
User blaz reports in a comment that "[one problem] with this solution is that provided path is path after PathMap is applied."
That is true.
If you use PathMap, then one possible way of overcoming this problem is as follows:
Move my code into a separate project which is compiled without the PathMap compiler option, and modify my code to return the path to the solution instead of the path to the project. Call that project SolutionSourcePath. Then, any projects that need their source path can refer to the SolutionSourcePath project to obtain the path to the solution, and from there compute the path to their own source code.