カスタムMSBuildタスクを作成するときに、C#コードから現在のプロジェクトディレクトリをどのように取得しますか?


133

パスがハードコーディングされた外部プログラムを実行する代わりに、現在のプロジェクトディレクトリを取得します。カスタムタスクのプロセスを使用して外部プログラムを呼び出しています。

どうすればいいですか?AppDomain.CurrentDomain.BaseDirectoryは、VS 2008の場所を教えてくれます。

回答:


112

この2つの方法のいずれかを試すことができます。

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

string startupPath = Environment.CurrentDirectory;

教えてください、どちらがあなたに良いと思われますか


85
上記の2つはbinディレクトリを指しているので、たとえば、ソリューション全体に対して1つのbinディレクトリがある場合、プロジェクトディレクトリ(またはプロジェクトディレクトリの下の2つのレベル)ではなく、そこにあなたを指します
matcheek

16
テストエクスプローラーを使用すると、両方のソリューションが期待どおりに機能しません。
Gucu112 2018

264
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 directory
string projectDirectory = Directory.GetParent(workingDirectory).Parent.FullName;

25
Directory.GetParent()の+1なので、\ bin \ Debugディレクトリを取得できません:)
Eystein Bye

5
カスタムターゲットCPUを使用するとどうなりますか?たとえば、ビルドをターゲットx64に設定すると、それらの間に別のフォルダーが作成されます。
Samir Aguiar

3
これが正解です。受け入れられた回答は、プロジェクトディレクトリではないbinディレクトリへのパスを返します。
pookie

@pookieの答えは、私の場合、再帰的に間違っています。これは* / {project} / binフォルダーを与えるので、.parentを連結する必要があります。
プリニー船長、

1
うまくいき、これが受け入れられる答えになるはずです
Ashok kumar Ganesan

41

プロジェクトがIISエクスプレスで実行されている場合、はEnvironment.CurrentDirectory、IIS Expressが置かれている場所(デフォルトパスはC:\ Program Files(x86)\ IIS Express)を指すことができ、プロジェクトが存在する場所を指すことはできません。


これはおそらく、さまざまな種類のプロジェクトに最も適したディレクトリパスです。

AppDomain.CurrentDomain.BaseDirectory

これはMSDNの定義です。

アセンブリリゾルバーがアセンブリをプローブするために使用するベースディレクトリを取得します。


20
9年後、誰かが実際に答えを出しました。
ジェフデイビス

.NET CoreにはAppDomainはありません。あなたはこのようなことをしなければならないでしょう。System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = context => InvokeBatchProcessors();
レイテンシー:

さらに、Visual Studio SDKを使用して、DTE2を使用するソリューション構成レイアウトから場所を取得できます。
レイテンシ

2
@待ち時間は.netコア3 WPFプロジェクトにあります
Alexander

うん、スペックを読んだ。確かに3,0のようなものはありません。それ以来、私はそれを使用しています。非常に満足して。私はこの3.0より前の記事を投稿したと思いますので、明確化に感謝します。
レイテンシ

18

これにより、現在実行中のディレクトリから2レベル上に移動してプロジェクトディレクトリも表示されます(すべてのビルドでプロジェクトディレクトリが返されるわけではありませんが、これが最も一般的です)。

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

もちろん、これをある種の検証/エラー処理ロジック内に含める必要があります。


IMOこれは最も柔軟な方法です。私はこれを単体テストと統合テストから使用していますが、そのパスは実際には1つのフォルダーのより深いです。
ソレイユ-MathieuPrévot2018年

これは何らかの理由で私にルートドライブを与えています。
プリニー船長、

10

ソリューションが配置されているディレクトリを知りたい場合は、次のようにする必要があります。

 var parent = Directory.GetParent(Directory.GetCurrentDirectory()).Parent;
            if (parent != null)
            {
                var directoryInfo = parent.Parent;
                string startDirectory = null;
                if (directoryInfo != null)
                {
                    startDirectory = directoryInfo.FullName;
                }
                if (startDirectory != null)
                { /*Do whatever you want "startDirectory" variable*/}
            }

GetCurrrentDirectory()メソッドのみを許可すると、デバッグまたはリリースのどちらの場合でも、ビルドフォルダーが取得されます。これがお役に立てば幸いです。検証を忘れると、次のようになります。

var startDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;

5

私もこれを探していました。HWCを実行するプロジェクトがあり、Webサイトをアプリツリーの外に置きたいのですが、デバッグ(またはリリース)ディレクトリに保持したくありません。FWIW、受け入れられたソリューション(およびこのソリューション)は、実行可能ファイルが実行されているディレクトリのみを識別します。

そのディレクトリを見つけるために、私は使用してきました

string startupPath = System.IO.Path.GetFullPath(".\\").

5

Gucu112の回答に基づいていますが、.NET Core Console / Windowアプリケーションの場合、次のようになります。

string projectDir = 
    Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\.."));

これを.NET Core WindowアプリケーションのxUnitプロジェクトで使用しています。


4

これを行う別の方法

string startupPath = System.IO.Directory.GetParent(@"./").FullName;

binフォルダーへのパスを取得する場合

string startupPath = System.IO.Directory.GetParent(@"../").FullName;

多分より良い方法があります=)


4

さらに別の不完全な解決策(ただし、他のいくつかのソリューションよりも少し完璧に近いかもしれません):

    protected static string GetSolutionFSPath() {
        return System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.FullName;
    }
    protected static string GetProjectFSPath() {
        return String.Format("{0}\\{1}", GetSolutionFSPath(), System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
    }

このバージョンは、現在のプロジェクトがソリューション用ではない場合でも、現在のプロジェクトのフォルダーを返しますStartup Project

これの最初の欠点は、すべてのエラーチェックを省略したことです。これは簡単に修正できますが、ドライブのルートディレクトリにプロジェクトを保存している場合、またはパスでジャンクションを使用している場合にのみ問題になるはずです(そのジャンクションはソリューションフォルダーの子孫です)。このシナリオはほとんどありません。 。とにかく、Visual Studioがこれらのセットアップのいずれかを処理できるかどうかは完全にはわかりません。

あなたがに実行することを別の(可能性が高い)の問題は、プロジェクト名があることである必要があり、それが発見されるためのプロジェクトのためのフォルダ名を一致させます。

もう1つの問題は、プロジェクトがソリューションフォルダー内にある必要があることです。これは通常問題ではありませんがAdd Existing Project to Solution、ソリューションにプロジェクトを追加するオプションを使用した場合、これはソリューションの編成方法とは異なる場合があります。

最後に、アプリケーションが作業ディレクトリを変更する場合、この値は現在の作業ディレクトリに関連して決定されるため、変更する前にこの値を保存する必要があります。

もちろん、これはすべて、プロジェクトプロパティダイアログのプロジェクトのBuild-> Output pathまたはDebug-> Working directoryオプションのデフォルト値を変更してはならないことも意味します。



4

このソリューションは、C#を介してASP.NET MVC5を使用するDevelopおよびTESTサーバーとPRODサーバーでうまく機能ます

var projectDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);

プロジェクト構成ファイルにプロジェクトディレクトリが必要な場合は、以下を使用します。

$(ProjectDir)

3

パブリックストリングについての最初の回答を最終的に磨いて回答を導き出した後、レジストリから値を読み取って目的の結果を得ることができることに気づきました。結局のところ、そのルートはさらに短くなりました。

まず、レジストリを操作できるように、Microsoft.Win32名前空間を含める必要があります。

using Microsoft.Win32;    // required for reading and / or writing the registry

ここにメインコードがあります:

RegistryKey Projects_Key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\9.0", false);
string DirProject = (string)Projects_Key.GetValue(@"DefaultNewProjectLocation");

この回答に関するメモ:

Visual Studio 2008 Professional Editionを使用しています。別のバージョン(2003、2005、2010など)を使用している場合は、SubKey文字列の「バージョン」部分(8.0、7.0など)を変更する必要がない場合があります。

私の回答の1つを使用し、質問するのが多すぎない場合は、使用した私の方法とその理由を知りたいと思います。幸運を。

  • dm

3

私も同様の状況にあり、無益なGoogleの後、プロジェクトのパスを取得するためにデバッグ/リリースパスの文字列値を変更するパブリック文字列を宣言しました。この方法を使用する利点は、現在のプロジェクトのディレクトリを使用するため、デバッグディレクトリまたはリリースディレクトリのどちらから作業していても問題ではないことです。

public string DirProject()
{
    string DirDebug = System.IO.Directory.GetCurrentDirectory();
    string DirProject = DirDebug;

    for (int counter_slash = 0; counter_slash < 4; counter_slash++)
    {
        DirProject = DirProject.Substring(0, DirProject.LastIndexOf(@"\"));
    }

    return DirProject;
}

その後、1行だけを使用して、いつでもそれを呼び出すことができます。

string MyProjectDir = DirProject();

これはほとんどの場合に機能します。


3

これを使用してプロジェクトディレクトリを取得します(私のために働いた):

string projectPath = 
    Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;

3
using System;
using System.IO;

// Get the current directory and make it a DirectoryInfo object.
// Do not use Environment.CurrentDirectory, vistual studio 
// and visual studio code will return different result:
// Visual studio will return @"projectDir\bin\Release\netcoreapp2.0\", yet 
// vs code will return @"projectDir\"
var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

// On windows, the current directory is the compiled binary sits,
// so string like @"bin\Release\netcoreapp2.0\" will follow the project directory. 
// Hense, the project directory is the great grand-father of the current directory.
string projectDirectory = currentDirectory.Parent.Parent.Parent.FullName;

2

私は仕事を成し遂げるために次の解決策を使用しました:

string projectDir =
    Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\.."));

2

試してください:

var pathRegex = new Regex(@"\\bin(\\x86|\\x64)?\\(Debug|Release)$", RegexOptions.Compiled);
var directory = pathRegex.Replace(Directory.GetCurrentDirectory(), String.Empty);

これは他のソリューションとは異なるソリューションで、可能なx86またはx64ビルドも考慮に入れています。


このソリューションは、TargetFrameworkがパスに含まれている新しいcsprojファイルにもほぼ存在します。
Glenn Watson

1
新しい.netcoreスタイル形式の場合、新しいRegex(@ "\\ bin(\\ x86 | \\ x64)?\(Debug | Release)(\ [a-zA-Z0-9。] *)?$"がありました、RegexOptions.Compiled)
Glenn Watson

1

最良のソリューション

string PjFolder1 =
    Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).
        Parent.Parent.FullName;

その他の解決策

string pjFolder2 = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)));

それをテストし、AppDomain.CurrentDomain.BaseDirectoryが過去のプロジェクトで私のために働いた、今私はデバッグフォルダーを取得します....選択された良い答えはうまくいきません!。

//Project DEBUG folder, but STILL PROJECT FOLDER
string pjDebugFolder = AppDomain.CurrentDomain.BaseDirectory;

//Visual studio folder, NOT PROJECT FOLDER
//This solutions just not work
string vsFolder = Directory.GetCurrentDirectory();
string vsFolder2 = Environment.CurrentDirectory;
string vsFolder3 = Path.GetFullPath(".\\");   

//Current PROJECT FOLDER
string ProjectFolder = 
    //Get Debug Folder object from BaseDirectory ( the same with end slash)
    Directory.GetParent(pjDebugFolder).
    Parent.//Bin Folder object
    Parent. //Project Folder object
    FullName;//Project Folder complete path

0

ソースプロジェクトディレクトリを確実に取得したい場合は、bin出力パスが次のように設定されていても、

  1. ビルド前のイベントコマンドラインを追加します(Visual Studio:プロジェクトプロパティ->ビルドイベント):

    echo $(MSBuildProjectDirectory) > $(MSBuildProjectDirectory)\Resources\ProjectDirectory.txt

  2. ProjectDirectory.txtファイルをプロジェクトのResources.resxに追加します(まだ存在しない場合は、プロジェクトを右クリックして、[新しい項目を追加]、[リソースファイル]の順にクリックします)。

  3. を使用したコードからのアクセスResources.ProjectDirectory

-1

これはVS2017 w / SDK Core MSBuild構成で動作します。

EnvDTE / EnvDTE80パッケージでNuGetを使用する必要があります。

COMまたは相互運用機能は使用しないでください。なんでも……ゴミ!!

 internal class Program {
    private static readonly DTE2 _dte2;

    // Static Constructor
    static Program() {
      _dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.15.0");
    }


    private static void FindProjectsIn(ProjectItem item, List<Project> results) {
      if (item.Object is Project) {
        var proj = (Project) item.Object;
        if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
          results.Add((Project) item.Object);
        else
          foreach (ProjectItem innerItem in proj.ProjectItems)
            FindProjectsIn(innerItem, results);
      }

      if (item.ProjectItems != null)
        foreach (ProjectItem innerItem in item.ProjectItems)
          FindProjectsIn(innerItem, results);
    }


    private static void FindProjectsIn(UIHierarchyItem item, List<Project> results) {
      if (item.Object is Project) {
        var proj = (Project) item.Object;
        if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
          results.Add((Project) item.Object);
        else
          foreach (ProjectItem innerItem in proj.ProjectItems)
            FindProjectsIn(innerItem, results);
      }

      foreach (UIHierarchyItem innerItem in item.UIHierarchyItems)
        FindProjectsIn(innerItem, results);
    }


    private static IEnumerable<Project> GetEnvDTEProjectsInSolution() {
      var ret = new List<Project>();
      var hierarchy = _dte2.ToolWindows.SolutionExplorer;
      foreach (UIHierarchyItem innerItem in hierarchy.UIHierarchyItems)
        FindProjectsIn(innerItem, ret);
      return ret;
    }


    private static void Main() {
      var projects = GetEnvDTEProjectsInSolution();
      var solutiondir = Path.GetDirectoryName(_dte2.Solution.FullName);

      // TODO
      ...

      var project = projects.FirstOrDefault(p => p.Name == <current project>);
      Console.WriteLine(project.FullName);
    }
  }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.