コードが含まれているアセンブリのパスを取得するにはどうすればよいですか?


781

現在のコードが存在するアセンブリのパスを取得する方法はありますか?呼び出し元のアセンブリのパスは必要ありません。コードが含まれているパスだけが必要です。

基本的に、ユニットテストでは、dllに関連して配置されているいくつかのxmlテストファイルを読み取る必要があります。テストdllがTestDriven.NETから実行されているか、MbUnit GUIから実行されているかに関係なく、パスが常に正しく解決されるようにしたい。

編集:人々は私が求めていることを誤解しているようです。

私のテストライブラリはsayにあります

C:\ projects \ myapplication \ daotests \ bin \ Debug \ daotests.dll

そして私はこのパスを取得したいと思います:

C:\ projects \ myapplication \ daotests \ bin \ Debug \

これまでの3つの提案は、MbUnit Guiから実行すると失敗します。

  • Environment.CurrentDirectoryc:\ Program Files \ MbUnit を与えます

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location 与え\ DocumentsとSettings \ジョージ\ローカル設定\一時\ .... \ DaoTests.dll:C

  • System.Reflection.Assembly.GetExecutingAssembly().Location 前と同じを与えます。


102
これはあなたの解決策です:var dir = AppDomain.CurrentDomain.BaseDirectory;
Jalal El-Shaer

7
これは受け入れられる解決策です。AppDomain.CurrentDomain.BaseDirectoryが正しいアプローチです。
aBetterGamer 2013年


2
私はここに来て、そのpacakgeディレクトリからJSONファイルを読み取るためのnugetパッケージのソリューションを探しました。nugetパッケージが実行されると、「AppDomain.CurrentDomain.BaseDirectory」は、nugetパッケージディレクトリではなく、実行中のプロジェクトディレクトリを指しているようです。これらのいずれも、nugetパッケージディレクトリを正しくターゲットにしていないようです。
Lucas

@Lucasいいえ、それはこの質問の内容ではないためです(実際に質問されたとき、nugetは存在しませんでした)-新しい質問を開始してそこにpingを送信してください。ほとんどの場合不可能です。ほとんどのプロジェクトでは、nugetディレクトリはpackagesslnファイルの隣にあります。しかし、あなたは物事をコンパイルして配布する際に何のSLNファイルなしpackagesディレクトリはありません。コンパイル中に、必要なもの(すべてではない)がbinディレクトリにコピーされます。最善の策は、ポストビルドスクリプトを使用して必要なファイルをコピーすることです。
ジョージマウアー

回答:


1036

単体テストでよく使用する次のプロパティを定義しました。

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}

このAssembly.Locationプロパティは、NUnit(アセンブリが一時フォルダーから実行される場所)を使用するときに面白い結果をもたらすことがあるのでCodeBase、URI形式のパスを提供し、最初にをUriBuild.UnescapeDataString削除して、通常のWindows形式に変更することをお勧めします。File://GetDirectoryName


29
これには私が遭遇した1つの問題があります。ディレクトリ名がc:\ My%20Directoryの場合、Uri.UnescapeDataStringは次を返します:c:\ My Directoryこれは、File.Exists( "c:\ My Directory \ MyFile.txt ")は、正しいパスが実際には" c:\ My%20Directory \ MyFile.txt "であるためfalseを返します。SVNパスにスペースがあり、チェックアウトするとスペースがエンコードされるため、これに遭遇しました。
row1

5
このメソッドはUNCパスでfalseを返すため、これを使用してFile.Exist()をチェックする場合は注意してください。代わりに@Keithの回答を使用してください。
AZ。

3
publicの前にstaticを置くことができることを知りませんでした。知って
よかった。

5
注:これはネットワークの場所(\\ REMOT_EPC \ Folderなど)では機能しません
Muxa

5
また、ディレクトリに番号記号「#」が含まれている場合、これは機能しません。Windowsでは、ディレクトリとファイル名にシャープ記号を使用できます。
Huemac

321

これは役に立ちますか?

//get the full location of the assembly with DaoTests in it
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location;

//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );

私の編集を参照してください、そうではありませんが、これはMbUnitがどのように処理するかについて奇妙なことですか?
ジョージマウアー

3
xmlファイルを、dllでコピーされたコンテンツ、またはdllから読み取られたリソースに設定します。
キース

22
または単にtypeof(DaoTests).Assembly
12

4
@SLaks @JohnySkovdal @Keith:皆さん、こんにちはAssembly.GetExecutingAssembly()。これは、「現在実行されているコード含むアセンブリ取得」(メソッドの説明からの)。これを自分のAddIn " EntitiesToDTOs "で使用します。実際の例については、AssemblyHelper.csを参照してください。
kzfabi

4
@John Silbyの投稿に問題がありました。UNCパスでは機能しないようです... \\ Server \ Folder \ File.extなど。これはトリックをしました。+1
ブルーベリー

312

それはこれと同じくらい簡単です:

var dir = AppDomain.CurrentDomain.BaseDirectory;

11
これは受け入れられる解決策です。AppDomain.CurrentDomain.BaseDirectoryが正しいアプローチです。
aBetterGamer 2013年

5
私の注意をこれに戻してくれてありがとう-それが私が質問したときに利用可能であったかどうかはわかりませんが、それは今です。
George Mauer 2013年

120
いいえ、これは間違っています。これは、現在実行中のコードではなく、元のエントリポイントのパスを返します。別のパスから手動でアセンブリをロードした場合、またはGACからアセンブリをロードした場合、誤った結果が返されます。この答えは正しいです。stackoverflow.com/ a / 283917/243557 Quickerはまだです Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
nathanchere 2013

9
実はこれは、Webアプリケーションでは動作しませんが、私の知る限り発見したとして、次の増強は、アプリケーションの任意のタイプのために働く必要があります:AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
イリヤChernomordik

4
これは、テストアセンブリの元のビンパスを取得するだけの場合(たとえば、サブフォルダー内の補助データファイルにアクセスする場合)、ユニットテストに最適です。テストアセンブリは、コードのエントリポイントです。
MarioDS

68

ジョンの回答と同じですが、少し冗長な拡張メソッドです。

public static string GetDirectoryPath(this Assembly assembly)
{
    string filePath = new Uri(assembly.CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}

今あなたはできる:

var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();

またはご希望の場合:

var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();

6
assembly代わりにAssembly.GetExecutingAssembly()ですか?
デュードパスカロウ2014年

3
デュードが指摘するように、あなたは引数を渡し、それを使用することに失敗しました。
Chris Moschini 2014年

4
この答えは、当面の質問に対しては明らかに間違っています。この回答の修正バージョンは、特定のアセンブリのパスを提供する可能性があります。ただし、ここでは実行中のアセンブリを具体的に探しているため、アセンブリを渡しても意味がありません。拡張メソッドは、ジョブには不適切なツールです。
エドワードブレイ

46

CodeBaseおよびUNCネットワーク共有を使用するときに私のために機能した唯一のソリューションは次のとおりです。

System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);

また、通常のURIでも機能します。


5
これは受け入れられる答えになるはずです。デフォルトのコードベースがUNCシェアを正しく処理しないのは本当にうんざりです。
ダニエルギルバート

これは、フォルダーにスペースが含まれ、神が他の文字を知っている場合にクラッシュします...
MarioDS

1
私はこれを頻繁に使用していて、失敗するシナリオを1つ見つけました。このコード行自体がNuGetパッケージの一部であり、アプリケーションで使用される場合です。私たちは、交換することによって、あまりにもそのシナリオをサポートすることができますGetExecutingAssembly()によってGetCallingAssembly()
Timo

@Timo:この変更に副作用があるかどうか確認しましたか?その場合は、回答を編集して修正を含めてください。
Ignacio Soler Garcia

@IgnacioSolerGarcia悲しいことに、私はそれが1層だけしか機能しなかったことを報告する必要があります。つまり、NuGetパッケージが別のNuGetパッケージによって呼び出された場合は失敗します。私は今(Chernomordikことで、このページのコメントから)これを使用しています:AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory。最初の部分はWebアプリケーション用で、2番目の部分は他のアプリケーション用です。
Timo

32

アセンブリがシャドウコピーされない限り、これは機能するはずです。

string path = System.Reflection.Assembly.GetExecutingAssembly().Location

14

これはどうですか:

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

11

ここでの実際の問題は、テストランナーがアセンブリを別の場所にコピーしていることだと思います。実行時にアセンブリがどこからコピーされたかを知る方法はありませんが、おそらくスイッチを切り替えて、アセンブリをどこから実行するかをシャドウディレクトリーにコピーしないようにテストランナーに指示できます。

もちろん、そのような切り替えは、テストランナーごとに異なる可能性があります。

XMLデータをリソースとしてテストアセンブリ内に埋め込むことを検討しましたか?


シャドウコピーの問題を指摘するための+1。ただし、から元の場所を特定することは確かに可能Assembly.CodeBaseです。
tm1 2017年

11
AppDomain.CurrentDomain.BaseDirectory

MbUnit GUIで動作します。


これは、asp.net Webアプリのルートディレクトリに関連するファイルを書き込むのに非常に
役立ちました

これが一般的に最もよく機能することがわかりました。不明な場合はそれを選択してください。
Erik Bergstedt 2016

10

私はこれがどんな種類のアプリケーションでもうまくいくと信じています:

AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory

1
私の実験では、これが最も簡単な答えであることを示しており、Webアプリケーションとコンソールアプリケーションだけでなく、単体テストやNuGetパッケージ(あらゆるレベルの再帰にネスト)からの呼び出しもカバーしています。
ティモ

8

私の知る限り、他のほとんどの回答にはいくつかの問題があります。

(Webベースではなく)ディスクベースの非GACアセンブリに対してこれを行う正しい方法は、現在実行中のアセンブリのCodeBaseプロパティを使用することです。

これはURL(file://)を返します。またはの文字列操作をいじるのではなくUnescapeDataString、これをのLocalPathプロパティを利用して最小限の手間で変換できますUri

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);

1
パスが含まれている場合は機能しません#EscapedCodeBase機能しますが、パスにたとえば%20Windowsパスで許可されている文字シーケンスである逐語的機能が含まれている場合、EscapedCodeBaseは機能しません)
Martin Ba

このコードをNuGetパッケージに含める場合は、で置き換えることGetExecutingAssembly()により、このシナリオを修正できますGetCallingAssembly()
Timo

8

これはどう ...

string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

次に、不要なものをハックオフします


7
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);

7

これがJohn SiblyのコードのVB.NETポートです。Visual Basicは大文字と小文字を区別しないので、彼の変数名のいくつかは型名と衝突していました。

Public Shared ReadOnly Property AssemblyDirectory() As String
    Get
        Dim codeBase As String = Assembly.GetExecutingAssembly().CodeBase
        Dim uriBuilder As New UriBuilder(codeBase)
        Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
        Return Path.GetDirectoryName(assemblyPath)
    End Get
End Property

6

この数年間、実際にこれについて言及した人はいません。素晴らしいApprovalTestsプロジェクトから学んだトリック。トリックは、元のディレクトリを見つけるためにアセンブリのデバッグ情報を使用することです。

これは、RELEASEモードでも、最適化を有効にしても、コンパイルされたマシンとは異なるマシンでは機能しません。

しかし、これにより、呼び出し元のソースコードファイルの場所からの相対パスが取得されます。

public static class PathUtilities
{
    public static string GetAdjacentFile(string relativePath)
    {
        return GetDirectoryForCaller(1) + relativePath;
    }
    public static string GetDirectoryForCaller()
    {
        return GetDirectoryForCaller(1);
    }


    public static string GetDirectoryForCaller(int callerStackDepth)
    {
        var stackFrame = new StackTrace(true).GetFrame(callerStackDepth + 1);
        return GetDirectoryForStackFrame(stackFrame);
    }

    public static string GetDirectoryForStackFrame(StackFrame stackFrame)
    {
        return new FileInfo(stackFrame.GetFileName()).Directory.FullName + Path.DirectorySeparatorChar;
    }
}

5

存在する現在のディレクトリ。

Environment.CurrentDirectory;  // This is the current directory of your application

ビルドで.xmlファイルをコピーすると、見つけられるはずです。

または

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;

アセンブリがシャドウコピーされている場合、これは問題になります。
消費者、2014年

+1520!Environment.CurrentDirectoryMSBuildタスククラスでリフレクションを使用していて、実行中のアセンブリがGACにあり、コードが別の場所にある場合に機能します。
バルカンレイヴン2014

4
一般に、CurrentDirectoryは実行可能ファイルがどこにあるかを教えてくれません。それはそれが使用されるものではありません。実行ファイルと同じ場所にあることがよくあるため、多くのプログラマーは違いを理解していません。次に、アプリケーションがCurrentDirectoryの適切な使用を理解することを期待していたエンドユーザーの一部に問題を引き起こします。
Bent Tranberg、2016年

5

Locationの代わりにAssembly.CodeBaseを使用しています:

Assembly a;
a = Assembly.GetAssembly(typeof(DaoTests));
string s = a.CodeBase.ToUpper(); // file:///c:/path/name.dll
Assert.AreEqual(true, s.StartsWith("FILE://"), "CodeBase is " + s);
s = s.Substring(7, s.LastIndexOf('/') - 7); // 7 = "file://"
while (s.StartsWith("/")) {
    s = s.Substring(1, s.Length - 1);
}
s = s.Replace("/", "\\");

正常に動作していますが、100%正しいかどうかはわかりません。http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspxのページには次のように書かれています:

"CodeBaseはファイルが見つかった場所へのURLですが、Locationは実際にロードされたパスです。たとえば、アセンブリがインターネットからダウンロードされた場合、CodeBaseは" http:// "で始まることがあります。 、ただしその場所は「C:\」で始まる場合があります。ファイルがシャドウコピーされた場合、場所はシャドウコピーディレクトリ内のファイルのコピーへのパスになります。CodeBaseが保証されていないことも知っておくとよいでしょう。 GACのアセンブリに設定されます。ただし、場所は常にディスクからロードされたアセンブリに設定されます。 "

あなたは可能コードベースの代わりの場所を使用します。


1
@Kiquenet:URIをパスに変換するだけの非常に多くのコード。確かにそれは改善される可能性があります。Mike SchallかSoMoSの答えを見てください。文字列レベルでURIを変換しようとするのではなく、適切なオブジェクトを使用してください。OK、Assembly.CodeBaseがURIやFileInfoなどのより適切なオブジェクトの代わりに文字列を返すことも不便です。
七つの

2

AppDomain.CurrentDomain.RelativeSearchPathでビンパスを取得できます


2

開発者がコードを変更して必要なスニペットを含めることができる場合、提案された回答はすべて機能しますが、コードを変更せずにこれを実行したい場合は、Process Explorerを使用できます。

システム上で実行中のすべてのdllがリストされます。実行中のアプリケーションのプロセスIDを特定する必要があるかもしれませんが、通常はそれほど難しくありません。

II内のdllでこれを行う方法の完全な説明を書きました-http ://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web -サーバ/


まず第一に、この記事のコードはかなりIIS中心であり、2番目に、一度に実行されているものではなく、現在ロードされているすべてのDLL を提供します(私はそう思います)。
ジョージマウアー2016

上記の例はiisに関連していますが、dllがiisの外部のプロセスで実行されている場合も同じ手順が適用されます。プロセスIDを特定するだけです。記事を更新してそのことに注意します。提案をありがとう。
ブライアン

2

Windowsフォームアプリでは、簡単に使用できます Application.StartupPath

DLLとコンソールアプリの場合、コードを覚えるのははるかに困難です...

string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

root += slash;
string settingsIni = root + "settings.ini"


1

パスに「#」記号が含まれていると、正しくないディレクトリが取得されます。そのため、UriBuilder.PathとUriBuilder.Fragmentの組み合わせであるJohn Siblyの回答の変更を使用します。

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        //modification of the John Sibly answer    
        string path = Uri.UnescapeDataString(uri.Path.Replace("/", "\\") + 
          uri.Fragment.Replace("/", "\\"));
        return Path.GetDirectoryName(path);
     }
}

0

これが私が思いついたものです。Webプロジェクト間では、単体テスト(nunitおよびresharperテストランナー) ; 私はこれがうまくいったことを発見しました。

ビルドの構成を検出するコードを探していますDebug/Release/CustomName。ああ、#if DEBUGだから誰かがそれを改善できるなら

自由に編集して改善してください。

アプリフォルダーを取得しています。Webルート、ユニットテストでテストファイルのフォルダーを取得するのに便利です。

public static string AppPath
{
    get
    {
        DirectoryInfo appPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

        while (appPath.FullName.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
                || appPath.FullName.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            appPath = appPath.Parent;
        }
        return appPath.FullName;
    }
}

binフォルダーの取得:リフレクションを使用してアセンブリを実行するのに便利です。ビルドプロパティのためにファイルがそこにコピーされた場合。

public static string BinPath
{
    get
    {
        string binPath = AppDomain.CurrentDomain.BaseDirectory;

        if (!binPath.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
            && !binPath.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            binPath = Path.Combine(binPath, "bin");
            //-- Please improve this if there is a better way
            //-- Also note that apps like webapps do not have a debug or release folder. So we would just return bin.
#if DEBUG
            if (Directory.Exists(Path.Combine(binPath, "Debug"))) 
                        binPath = Path.Combine(binPath, "Debug");
#else
            if (Directory.Exists(Path.Combine(binPath, "Release"))) 
                        binPath = Path.Combine(binPath, "Release");
#endif
        }
            return binPath;
    }
}

0

これはうまくいくはずです:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
Assembly asm = Assembly.GetCallingAssembly();
String path = Path.GetDirectoryName(new Uri(asm.EscapedCodeBase).LocalPath);

string strLog4NetConfigPath = System.IO.Path.Combine(path, "log4net.config");

これを使用して、DLLファイルライブラリをいくつかの構成ファイルと共に展開します(これは、DLLファイル内からlog4netを使用するためです)。


fileMapここでは何を使用していますか?
ジョージマウアー2013年

0

ロケーションの検索に適切なソリューションが見つかりました。

var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;

これは、すでにトップクラスの答えの一つである、このような状況では動作しないものとして問題に明示的に言及されています。
ジョージマウアー2015

お見逃しなく!明らかに私は徹底的に読み通しませんでした。
Tez Wingfield

0

私はNUnit過去に同じ振る舞いをしました。デフォルトではNUnit、アセンブリを一時ディレクトリにコピーします。この動作はNUnit設定で変更できます。

ここに画像の説明を入力してください

多分TestDriven.NETMbUnitGUIは同じ設定を持っています。


-3

これを使用してBin Directoryへのパスを取得します。

var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i); 

あなたはこの結果を得ます:

「c:\ users \ ricooley \ documents \ visual studio 2010 \ Projects \ Windows_Test_Project \ Windows_Test_Project \ bin」


6
ここにPath.getDirectoryNameを回避する理由が見当たらない
Max Keller

@MaxKeller理由がわからなくても、それが正しいとは限りません。Path.GetDirectoryNameのこの代替メソッドは、10倍高速です。
Ruslan Veselov 2015年

-3

ウェブアプリケーション?

Server.MapPath("~/MyDir/MyFile.ext")

2
@christiandevこれは答えですが、おそらく間違った質問に対する答えのようです。質問から、これはWebアプリケーションではなく、MbUnitで実行されているアセンブリであることは明らかです。そうは言っても、Asp.Netのシャドウコピーのため、答えはまだ正確ではありません(この質問にたどり着いた人が探しているものと考えられます)。
ジョージマウアー2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.