문제

현재 코드가 있는 어셈블리의 경로를 얻을 수 있는 방법이 있습니까?나는 호출 어셈블리의 경로를 원하지 않고 단지 코드가 포함된 경로만을 원합니다.

기본적으로 내 단위 테스트는 dll에 상대적인 위치에 있는 일부 XML 테스트 파일을 읽어야 합니다.테스트 dll이 TestDriven.NET, MbUnit GUI 또는 다른 것에서 실행되는지 여부에 관계없이 경로가 항상 올바르게 확인되기를 원합니다.

편집하다:사람들이 내가 묻는 것을 오해하는 것 같습니다.

내 테스트 라이브러리는 say에 있습니다.

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

그리고 나는 이 경로를 얻고 싶습니다:

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

MbUnit Gui에서 실행할 때 지금까지 세 가지 제안이 실패했습니다.

  • Environment.CurrentDirectory준다 c:\Program Files\MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location준다 C : 문서 및 설정 George Local 설정 temp .... daotests.dll

  • System.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(어셈블리가 임시 폴더에서 실행되는 경우)을 사용할 때 때때로 재미있는 결과를 제공하므로 저는 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 Sily 코드의 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/assemble-codebase-vs-assemble-location.aspx 말한다:

"CodeBase는 파일이 발견된 위치에 대한 URL이고, Location은 파일이 실제로 로드된 경로입니다.예를 들어 어셈블리를 인터넷에서 다운로드한 경우 해당 CodeBase는 "http://"로 시작될 수 있지만 해당 위치는 "C:\"로 시작될 수 있습니다.파일이 섀도 복사된 경우 위치는 섀도 복사본 디렉터리에 있는 파일 복사본의 경로가 됩니다.GAC의 어셈블리에 대해 CodeBase가 설정되지 않을 수도 있다는 점을 알아두는 것도 좋습니다.그러나 디스크에서 로드된 어셈블리에 대해서는 위치가 항상 설정됩니다."

5월 위치 대신 CodeBase를 사용하고 싶습니다.

내가 알 수 있는 한, 대부분의 다른 답변에는 몇 가지 문제가 있습니다.

이 작업을 수행하는 올바른 방법은 디스크 기반(웹 기반과 반대), 비 GAC 어셈블리 현재 실행 중인 어셈블리를 사용하는 것입니다. CodeBase 재산.

그러면 URL(file://).장난치는 대신에 문자열 조작 또는 UnescapeDataString, 이는 다음을 활용하여 최소한의 소란으로 변환될 수 있습니다. LocalPath 의 자산 Uri.

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

지난 몇 년 동안 실제로 이것을 언급한 사람은 아무도 없었습니다.내가 멋진 사람에게서 배운 비법 승인 테스트 프로젝트.비결은 어셈블리의 디버깅 정보를 사용하여 원래 디렉터리를 찾는 것입니다.

이는 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.relativeSearchPath로 빈 경로를 얻을 수 있습니다

제안된 답변은 모두 개발자가 필수 코드 조각을 포함하도록 코드를 변경할 수 있을 때 작동하지만, 코드를 변경하지 않고 이 작업을 수행하려면 프로세스 탐색기를 사용할 수 있습니다.

시스템에서 실행 중인 모든 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 Sily 답변의 수정 사항을 사용합니다.

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);
     }
}

이것이 내가 생각해 낸 것입니다. 웹 프로젝트 사이에서 단위 테스트(nunit 및 resharper 테스트 실행기);나는 이것이 나에게 효과적이라는 것을 알았습니다.

빌드가 어떤 구성에 있는지 감지하는 코드를 찾고 있었습니다. 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 설정:

enter image description here

아마도 TestDriven.NET 그리고 MbUnit GUI는 동일한 설정을 갖습니다.

나는 이것을 사용하여 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")
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top