코드가 있는 어셈블리의 경로를 가져오려면 어떻게 해야 합니까?
현재 코드가 있는 어셈블리의 경로를 가져올 수 있는 방법이 있습니까?호출 어셈블리의 경로가 아니라 코드가 포함된 경로를 원합니다.
기본적으로 내 유닛 테스트는 dll에 관련된 xml 테스트 파일을 읽어야 합니다.테스트 DLL이 TestDriven에서 실행되는지 여부에 관계없이 경로가 항상 올바르게 확인되기를 원합니다.NET, MbUnit GUI 또는 다른 것.
편집: 사람들이 제가 묻는 것을 오해하고 있는 것 같습니다.
내 시험 라이브러리는 say에 있습니다.
C:\projects\myapplication\daotests\bin\Debug\daotests.dll
저는 이 길을 가고 싶습니다.
C:\projects\myapplication\daotests\bin\Debug\
MbUnitGui에서 실행할 때 지금까지의 세 가지 제안은 실패합니다.
Environment.CurrentDirectory
c:\Program Files\MbUnit 제공System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location
C 제공:\문서 및 설정\조지\로컬 설정\온도\...\DaoTests.dllSystem.Reflection.Assembly.GetExecutingAssembly().Location
이전과 동일한 값을 제공합니다.
참고: 어셈블리.CodeBase는 .NET Core/에서 더 이상 사용되지 않습니다.NET 5+: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.codebase?view=net-5.0
원답:
유닛 테스트에서 자주 사용하는 속성을 다음과 같이 정의했습니다.
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 URI 형식을 합니다.UriBuild.UnescapeDataString
합니다.File://
처에음고, 리그고.GetDirectoryName
일반 창 형식으로 변경합니다.
이게 도움이 되나요?
//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;
존의 답변과 동일하지만, 약간 덜 장황한 확장 방법입니다.
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 Network 공유를 사용할 때 효과가 있었던 유일한 솔루션은 다음과 같습니다.
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
또한 일반 URI에서도 작동합니다.
어셈블리를 섀도 복사본으로 복사하지 않는 한 다음과 같이 작동합니다.
string path = System.Reflection.Assembly.GetExecutingAssembly().Location
저는 이것이 모든 종류의 애플리케이션에 적용될 것이라고 믿습니다.
AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
다음은 어떻습니까?
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
.net framework 4.6 / .net core 1.0부터 AppContext가 있습니다.BaseDirectory - 다음과 같은 결과를 제공해야 합니다.AppDomain.CurrentDomain.BaseDirectory
AppDomains가 .net core 1.x /.net 표준 1.x API의 일부가 아니었다는 점을 제외하면,
AppContext.BaseDirectory
편집: 문서에는 다음과 같은 내용이 포함됩니다.
.NET 5.0 이상 버전에서는 번들 어셈블리의 경우 반환되는 값이 호스트 실행 파일의 포함 디렉토리입니다.
.NET 5.0 이상 버전에서는 번들 어셈블리의 경우 반환되는 값이 빈 문자열입니다.
AppDomain.CurrentDomain.BaseDirectory
MbUnit GUI와 함께 작동합니다.
실제 문제는 테스트 실행자가 어셈블리를 다른 위치로 복사하는 것입니다.런타임에 어셈블리가 복사된 위치를 알 수 있는 방법은 없지만 테스트 실행자에게 어셈블리를 원래 위치에서 실행하고 섀도 디렉터리에 복사하지 않도록 스위치를 돌릴 수 있습니다.
물론 이러한 스위치는 테스트 주자마다 다를 수 있습니다.
XML 데이터를 테스트 어셈블리 내의 리소스로 포함하는 것을 고려해 본 적이 있습니까?
이건 어때요...
string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
그러면 필요 없는 것만 잘라내세요.
tl;dr
어셈블리와 DLL 파일의 개념이 다릅니다.어셈블리가 로드된 방식에 따라 경로 정보가 손실되거나 전혀 사용할 수 없습니다.그러나 대부분의 경우 제공된 답변은 효과가 있습니다.
질문과 이전 답이 가지고 있는 한 가지 오해가 있습니다.대부분의 경우 제공된 답변은 정상적으로 작동하지만 현재 코드가 있는 어셈블리의 올바른 경로를 얻을 수 없는 경우가 있습니다.
실행 코드를 포함하는 어셈블리와 어셈블리를 포함하는 dll 파일의 개념이 밀접하게 연결되어 있지 않습니다.어셈블리는 DLL 파일에서 가져올 수 있지만 그럴 필요는 없습니다.
Assembly.Load(Byte[])
(MSDN) 방법 메모리의 바이트 배열에서 직접 어셈블리를 로드할 수 있습니다.바이트 배열이 어디에서 왔는지는 중요하지 않습니다.파일에서 로드하거나 인터넷에서 다운로드하거나 동적으로 생성할 수 있습니다.
다음은 바이트 배열에서 어셈블리를 로드하는 예제입니다.파일이 로드된 후 경로 정보가 손실됩니다.원래 파일 경로를 가져올 수 없으며 이전에 설명한 모든 메서드가 작동하지 않습니다.
이 방법은 "D:/소프트웨어/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe"에 있는 실행 어셈블리에 있습니다.
static void Main(string[] args)
{
var fileContent = File.ReadAllBytes(@"C:\Library.dll");
var assembly = Assembly.Load(fileContent);
// Call the method of the library using reflection
assembly
?.GetType("Library.LibraryClass")
?.GetMethod("PrintPath", BindingFlags.Public | BindingFlags.Static)
?.Invoke(null, null);
Console.WriteLine("Hello from Application:");
Console.WriteLine($"GetViaAssemblyCodeBase: {GetViaAssemblyCodeBase(assembly)}");
Console.WriteLine($"GetViaAssemblyLocation: {assembly.Location}");
Console.WriteLine($"GetViaAppDomain : {AppDomain.CurrentDomain.BaseDirectory}");
Console.ReadLine();
}
이 클래스는 Library.dll에 있습니다.
public class LibraryClass
{
public static void PrintPath()
{
var assembly = Assembly.GetAssembly(typeof(LibraryClass));
Console.WriteLine("Hello from Library:");
Console.WriteLine($"GetViaAssemblyCodeBase: {GetViaAssemblyCodeBase(assembly)}");
Console.WriteLine($"GetViaAssemblyLocation: {assembly.Location}");
Console.WriteLine($"GetViaAppDomain : {AppDomain.CurrentDomain.BaseDirectory}");
}
}
완전성을 위해 다음과 같은 구현이 있습니다.GetViaAssemblyCodeBase()
두 에 대해 동일합니다.
private static string GetViaAssemblyCodeBase(Assembly assembly)
{
var codeBase = assembly.CodeBase;
var uri = new UriBuilder(codeBase);
return Uri.UnescapeDataString(uri.Path);
}
Runner는 다음 출력을 인쇄합니다.
Hello from Library:
GetViaAssemblyCodeBase: D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe
GetViaAssemblyLocation:
GetViaAppDomain : D:\Software\DynamicAssemblyLoad\DynamicAssemblyLoad\bin\Debug\
Hello from Application:
GetViaAssemblyCodeBase: D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe
GetViaAssemblyLocation:
GetViaAppDomain : D:\Software\DynamicAssemblyLoad\DynamicAssemblyLoad\bin\Debug\
보다시피 코드 기반, 위치 또는 기본 디렉터리가 모두 올바르지 않습니다.
제가 알기로는 다른 답변들은 대부분 몇 가지 문제가 있습니다.
웹 기반이 아닌 디스크 기반의 비 GACed 어셈블리에서 이 작업을 수행하는 올바른 방법은 현재 실행 파일을 사용하는 것입니다.CodeBase
소유물.
을 반환합니다(URL은 "URL"입니다).file://
) 문자열을 조작하는 대신, 또는 를 사용하여 최소한의 혼란으로 변환할 수 있습니다.LocalPath
의 Uri
.
var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
이것은 존 실리의 코드의 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
지금까지 아무도 이것에 대해 언급하지 않았습니다.멋진 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;
}
}
어셈블리를 사용하고 있습니다.위치 대신 코드베이스:
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:\"로 시작할 수 있습니다. 파일이 섀도 복사본인 경우 위치는 섀도 복사본 디르에 있는 파일 복사본의 경로가 됩니다. 또한 GAC의 어셈블리에 대해 CodeBase가 설정되지 않을 수도 있습니다. 그러나 디스크에서 로드된 어셈블리에 대해서는 항상 위치가 설정됩니다."
위치 대신 코드베이스를 사용할 수 있습니다.
사용자가 있는 현재 디렉터리입니다.
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;
앱도메인별로 bin 경로를 얻을 수 있습니다.현재 도메인.상대 검색 경로
제안된 모든 답변은 개발자가 필요한 스니펫을 포함하도록 코드를 변경할 수 있을 때 작동하지만, 코드를 변경하지 않고 이 작업을 수행하려면 프로세스 탐색기를 사용할 수 있습니다.
시스템에서 실행 중인 모든 dll이 나열됩니다. 실행 중인 응용 프로그램의 프로세스 ID를 확인해야 할 수도 있지만, 일반적으로 그렇게 어렵지는 않습니다.
저는 II 내부의 dll에 대해 어떻게 이것을 하는지에 대한 완전한 설명을 썼습니다 - http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web-server/
윈도우 폼 앱에서, 당신은 간단히 사용할 수 있습니다.Application.StartupPath
DLL과 콘솔 앱의 경우 코드를 기억하기가 훨씬 어렵습니다.
string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
root += slash;
string settingsIni = root + "settings.ini"
경로에 '#' 기호가 있으면 잘못된 디렉터리가 표시됩니다.그래서 저는 UriBuilder라는 John Sably 답변의 수정을 사용합니다.경로 및 URIBuilder.조각:
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);
}
}
ASP.Net의 경우 작동하지 않습니다.Why AppDomain에서 더 나은 솔루션을 찾았습니다.현재 도메인.BaseDirectory가 asp.net app에 "bin"을(를) 포함하지 않습니다.Win Application과 ASP 모두에서 작동합니다.인터넷 웹 응용 프로그램.
public string ApplicationPath
{
get
{
if (String.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath))
{
return AppDomain.CurrentDomain.BaseDirectory; //exe folder for WinForms, Consoles, Windows Services
}
else
{
return AppDomain.CurrentDomain.RelativeSearchPath; //bin folder for Web Apps
}
}
}
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);
이것이 제가 생각해 낸 것입니다.웹 프로젝트 사이에 유닛 테스트(unit 및 resharper test runner)가 있습니다. 저는 이것이 저에게 효과가 있다는 것을 알았습니다.
되어 있는지 할 수 있는 .Debug/Release/CustomName
아아그, 그,.#if DEBUG
그래서 누군가 그것을 개선할 수 있다면요!
자유롭게 편집하고 개선할 수 있습니다.
앱 폴더를 가져오는 중입니다.테스트 파일의 폴더를 가져오기 위한 웹 루트, 유닛 테스트에 유용합니다.
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;
저도 같은 행동을 했습니다.NUnit
과거에기본적으로NUnit
어셈블리를 임시 디렉토리에 복사합니다.은 에이동변수있다습에서 할 수 .NUnit
설정:
아마도요.TestDriven.NET
그리고.MbUnit
GUI 설정이 동일합니다.
이를 사용하여 Bin 디렉토리의 경로를 가져옵니다.
var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i);
다음과 같은 결과를 얻을 수 있습니다.
"c:\users\ricooly\documents\visual studio 2010\Projects\"Windows_테스트_프로젝트\Windows_테스트_프로젝트\bin"
언급URL : https://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in
'source' 카테고리의 다른 글
#c#에서 디버그가 아닌 경우? (0) | 2023.05.17 |
---|---|
mongoose 스키마 생성 (0) | 2023.05.17 |
WPF: 콘텐츠 제어를 위한 데이터 템플릿 트리거를 설정하는 방법은 무엇입니까? (0) | 2023.05.17 |
Python: 목록에서 판다 데이터 프레임 만들기 (0) | 2023.05.17 |
파이썬에서 환경 변수에 액세스하려면 어떻게 해야 합니까? (0) | 2023.05.17 |