コードが含まれているアセンブリのパスを取得するにはどうすればよいですか?
-
09-06-2019 - |
質問
現在のコードが存在するアセンブリのパスを取得する方法はありますか?呼び出し元アセンブリのパスは必要ありません。コードを含むアセンブリのパスだけが必要です。
基本的に、私の単体テストでは、DLL に相対的に配置されているいくつかの XML テスト ファイルを読み取る必要があります。テスト DLL が TestDriven.NET、MbUnit GUI、または他のものから実行されるかどうかに関係なく、パスが常に正しく解決されるようにしたいと考えています。
編集:人々は私の質問を誤解しているようです。
私のテストライブラリはたとえば次の場所にあります
C:\projects\myapplication\daotests\bin\Debug\daotests.dll
そして私はこのパスを取得したいと思います:
C:\projects\myapplication\daotests\bin\Debug\
MbUnit Gui から実行すると、これまでの 3 つの提案は失敗します。
Environment.CurrentDirectory
与える c:\Program Files\MbUnitSystem.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location
与える c:ドキュメントと設定 george local settings temp .... daotests.dllSystem.Reflection.Assembly.GetExecutingAssembly().Location
前と同じものを与えます。
解決
単体テストでよく使用するため、次のプロパティを定義しました。
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
を削除します File://
初めに、そして GetDirectoryName
通常の Windows 形式に変更します。
他のヒント
これは役に立ちますか?
//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 );
それは次のように簡単です。
var dir = AppDomain.CurrentDomain.BaseDirectory;
John の答えと同じですが、少し冗長ではない拡張メソッドです。
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();
CodeBase と UNC ネットワーク共有を使用する場合にうまくいった唯一の解決策は次のとおりです。
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
通常の URI でも動作します。
アセンブリがそうでない限り、これは機能するはずです シャドウがコピーされました:
string path = System.Reflection.Assembly.GetExecutingAssembly().Location
これはどうですか:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
ここでの本当の問題は、テスト ランナーがアセンブリを別の場所にコピーしていることだと思います。実行時にアセンブリがどこからコピーされたかを知る方法はありませんが、スイッチを切り替えて、アセンブリをシャドウ ディレクトリにコピーせずに、アセンブリをその場所から実行するようにテスト ランナーに指示することはできるでしょう。
もちろん、そのようなスイッチはテスト ランナーごとに異なる可能性があります。
XML データをテスト アセンブリ内にリソースとして埋め込むことを検討したことがありますか?
AppDomain.CurrentDomain.BaseDirectory
MbUnit GUI で動作します。
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
以下は、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
これはどう ...
string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
あとは不要な部分をハックするだけです
あなたが存在する現在のディレクトリ。
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;
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 はファイルが実際にロードされたパスです。たとえば、アセンブリがインターネットからダウンロードされた場合、そのコードベースは「http://」で始まる可能性がありますが、その場所は「C:\」で始まる可能性があります。ファイルがシャドウ コピーされた場合、場所はシャドウ コピー ディレクトリ内のファイルのコピーへのパスになります。コードベースが GAC のアセンブリに設定されることが保証されていないことも知っておくとよいでしょう。ただし、ディスクから読み込まれたアセンブリの場所は常に設定されます。"
あなた 5月 Location の代わりに CodeBase を使用したいと考えています。
私の知る限り、他のほとんどの回答にはいくつかの問題があります。
これを行う正しい方法は、 (Web ベースではなく) ディスクベース、非 GAC アセンブリ 現在実行中のアセンブリを使用することです CodeBase
財産。
これにより URL (file://
)。いじる代わりに 文字列操作 または UnescapeDataString
, 、これは、 LocalPath
の財産 Uri
.
var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
ここ何年もの間、誰もこの件について実際に言及していませんでした。すごい人から学んだコツ 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;
}
}
appdomain.currentdomain.lelativesearchPathによってビンパスを取得できます
提案された答えはすべて、開発者がコードを変更して必要なスニペットを含めることができる場合に機能しますが、コードを変更せずにこれを実行したい場合は、Process Explorer を使用できます。
システム上で実行中のすべての DLL が一覧表示されます。実行中のアプリケーションのプロセス ID を確認する必要がある場合がありますが、通常はそれほど難しくありません。
II 内の DLL に対してこれを行う方法の完全な説明を書きました - http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web-server/
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"
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);
パスに「#」記号が含まれている場合、間違ったディレクトリが取得されます。そこで、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);
}
}
これが私が思いついたものです。 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;
}
}
これは機能するはずです:
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 を使用するためです)。
私のソリューションは位置の取得には適切であると思います。
var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;
これを使用して Bin ディレクトリへのパスを取得します。
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"
ウェブアプリケーション?
Server.MapPath("~/MyDir/MyFile.ext")