Coder Perfect

When establishing a custom MSBuild job, how do you access the current project directory from C# code?

Problem

I’d rather receive the current Project Dir than start an external program with its path hardcoded. I’m utilizing a process in the custom task to call an external program.

How would I go about doing that? AppDomain. CurrentDomain. BaseDirectory simply tells me where to get Visual Studio 2008.

Asked by sean

Solution #1

using System;
using System.IO;

// This will get the current WORKING directory (i.e. \bin\Debug)
string workingDirectory = Environment.CurrentDirectory;
// or: Directory.GetCurrentDirectory() gives the same result

// This will get the current PROJECT bin directory (ie ../bin/)
string projectDirectory = Directory.GetParent(workingDirectory).Parent.FullName;

// This will get the current PROJECT directory
string projectDirectory = Directory.GetParent(workingDirectory).Parent.Parent.FullName;

Answered by mohammed sameeh

Solution #2

One of these two strategies can be used.

string startupPath = System.IO.Directory.GetCurrentDirectory();

string startupPath = Environment.CurrentDirectory;

Which do you think is the better option?

Answered by Iralda Mitro

Solution #3

If your project is running on IIS Express, the Environment.CurrentDirectory could be pointing to IIS Express instead of your project (the default path is C:Program Files (x86)IIS Express).

This is most likely the best directory route for a variety of projects.

AppDomain.CurrentDomain.BaseDirectory

The MSDN definition can be found here.

Answered by hina10531

Solution #4

The haphazardness of all of the solutions posted so far astounded and astounded me.

The only proper1 way to access the root folder of a C# project is to use the [CallerFilePath] attribute to acquire the complete path name of a source file, then subtract the filename + extension from it to get the project path.

Here’s how to do it correctly:

Add the following code to the file ProjectSourcePath.cs in the root folder of your project:

internal static class ProjectSourcePath
{
    private const  string  myRelativePath = nameof(ProjectSourcePath) + ".cs";
    private static string? lazyValue;
    public  static string  Value => lazyValue ??= calculatePath();

    private static string calculatePath()
    {
        string pathName = GetSourceFilePathName();
        Assert( pathName.EndsWith( myRelativePath, StringComparison.Ordinal ) );
        return pathName.Substring( 0, pathName.Length - myRelativePath.Length );
    }
}

If you don’t have it, just remove the?. The string? requires a very recent version of C# with #nullable enabled; if you don’t have it, just remove the?

The Assert() function is my own; you can use your own or leave it out if you choose to live recklessly.

The following is the definition for GetSourceFilePathName():

using System.Runtime.CompilerServices

    public static string GetSourceFilePathName( [CallerFilePath] string? callerFilePath = null ) //
        => callerFilePath ?? "";

Once you have the above, you can put it to use in the following way:

string projectSourcePath = ProjectSourcePath.Value;

1 ‘appropriate,’ as in: foolproof; certain; without assumptions; not held together by shoestrings; not likely to shatter horrifically without warning when unrelated things are changed; etc.

Answered by Mike Nakis

Solution #5

Navigating two levels up from the current execution directory will also return the project directory (this will not return the project directory for every build, but it is the most typical).

System.IO.Path.GetFullPath(@"..\..\")

Of course, this should be included within some type of validation/error handling logic.

Answered by nh43de

Post is based on https://stackoverflow.com/questions/816566/how-do-you-get-the-current-project-directory-from-c-sharp-code-when-creating-a-c