Frage

Gibt es eine Möglichkeit, den Pfad für die Assembly abzurufen, in der sich der aktuelle Code befindet?Ich möchte nicht den Pfad der aufrufenden Assembly, sondern nur den, der den Code enthält.

Grundsätzlich muss mein Komponententest einige XML-Testdateien lesen, die sich relativ zur DLL befinden.Ich möchte, dass der Pfad immer korrekt aufgelöst wird, unabhängig davon, ob die Test-DLL über TestDriven.NET, die MbUnit-GUI oder etwas anderes ausgeführt wird.

Bearbeiten:Die Leute scheinen meine Frage falsch zu verstehen.

Meine Testbibliothek befindet sich in sagen wir

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

und ich möchte diesen Weg bekommen:

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

Die drei Vorschläge scheitern bisher, wenn ich über die MbUnit-GUI starte:

  • Environment.CurrentDirectorygibt c:\Programme\MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Locationgibt C: Dokumente und Einstellungen George Lokale Einstellungen temp .... Daotests.dll

  • System.Reflection.Assembly.GetExecutingAssembly().Locationergibt das Gleiche wie das vorherige.

War es hilfreich?

Lösung

Ich habe die folgende Eigenschaft definiert, da wir sie häufig bei Unit-Tests verwenden.

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

Der Assembly.Location Die Eigenschaft führt manchmal zu seltsamen Ergebnissen, wenn Sie NUnit verwenden (wo Assemblys aus einem temporären Ordner ausgeführt werden), daher bevorzuge ich die Verwendung CodeBase Das gibt Ihnen dann den Pfad im URI-Format UriBuild.UnescapeDataString entfernt die File:// am Anfang, und GetDirectoryName ändert es in das normale Windows-Format.

Andere Tipps

Hilft das?

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

So einfach ist es:

var dir = AppDomain.CurrentDomain.BaseDirectory;

Wie Johns Antwort, jedoch mit einer etwas weniger ausführlichen Erweiterungsmethode.

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

Jetzt können Sie Folgendes tun:

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

oder wenn Sie es vorziehen:

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

Die einzige Lösung, die für mich bei der Verwendung von CodeBase- und UNC-Netzwerkfreigaben funktioniert hat, war:

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

Es funktioniert auch mit normalen URIs.

Dies sollte funktionieren, es sei denn, die Baugruppe ist Schatten kopiert:

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

Was ist damit:

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

Ich vermute, dass das eigentliche Problem darin besteht, dass Ihr Testläufer Ihre Baugruppe an einen anderen Speicherort kopiert.Zur Laufzeit gibt es keine Möglichkeit zu erkennen, woher die Assembly kopiert wurde, aber Sie können wahrscheinlich einen Schalter umlegen, um den Testläufer anzuweisen, die Assembly dort auszuführen, wo sie sich befindet, und sie nicht in ein Schattenverzeichnis zu kopieren.

Natürlich dürfte ein solcher Wechsel bei jedem Testläufer unterschiedlich ausfallen.

Haben Sie darüber nachgedacht, Ihre XML-Daten als Ressourcen in Ihre Testassembly einzubetten?

AppDomain.CurrentDomain.BaseDirectory

Funktioniert mit der MbUnit-GUI.

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

Hier ist eine VB.NET-Portierung des Codes von John Sably.Visual Basic unterscheidet nicht zwischen Groß- und Kleinschreibung, daher kollidierten einige seiner Variablennamen mit Typnamen.

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

Wie wäre es damit ...

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

Dann hacken Sie einfach ab, was Sie nicht brauchen

Das aktuelle Verzeichnis, in dem Sie sich befinden.

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

Wenn Sie die XML-Datei mit Build kopieren, sollten Sie sie finden.

oder

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

// The location of the Assembly
assembly.Location;

Ich habe Assembly.CodeBase anstelle von Location verwendet:

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("/", "\\");

Es hat funktioniert, aber ich bin mir nicht mehr sicher, ob es 100 % korrekt ist.Die Seite unter http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx sagt:

„Die CodeBase ist eine URL zu dem Ort, an dem die Datei gefunden wurde, während der Speicherort der Pfad ist, in den sie tatsächlich geladen wurde.Wenn die Assembly beispielsweise aus dem Internet heruntergeladen wurde, beginnt ihre Codebasis möglicherweise mit „http://“, ihr Speicherort jedoch möglicherweise mit „C:\“.Wenn die Datei schattenkopiert wurde, wäre der Speicherort der Pfad zur Kopie der Datei im Schattenkopieverzeichnis.Es ist auch gut zu wissen, dass es nicht garantiert ist, dass die CodeBase für Assemblys im GAC festgelegt ist.Der Speicherort wird jedoch immer für Baugruppen festgelegt, die von der Festplatte geladen werden."

Du Mai Sie möchten CodeBase anstelle von Location verwenden.

Soweit ich das beurteilen kann, weisen die meisten anderen Antworten einige Probleme auf.

Der richtige Weg, dies für a zu tun Festplattenbasierte (im Gegensatz zur webbasierten), nicht-GAC-Assembly besteht darin, die aktuell ausgeführten Assemblys zu verwenden CodeBase Eigentum.

Dies gibt eine URL zurück (file://).Anstatt herumzuspielen String-Manipulation oder UnescapeDataString, dies kann mit minimalem Aufwand durch Hebelwirkung umgewandelt werden LocalPath Eigentum von Uri.

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

In all den Jahren hat niemand dies wirklich erwähnt.Ein Trick, den ich von den Großartigen gelernt habe ApprovalTests-Projekt.Der Trick besteht darin, dass Sie die Debugging-Informationen in der Assembly verwenden, um das ursprüngliche Verzeichnis zu finden.

Dies funktioniert weder im RELEASE-Modus noch mit aktivierten Optimierungen noch auf einem anderen Computer als dem, auf dem es kompiliert wurde.

Aber dadurch erhalten Sie Wege, die es gibt relativ zum Speicherort der Quellcodedatei, von der aus Sie sie aufrufen

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

Sie können den Bin -Pfad von appdomain.currentdomain.relativeSearchPath erhalten

Alle vorgeschlagenen Antworten funktionieren, wenn der Entwickler den Code so ändern kann, dass er das erforderliche Snippet enthält. Wenn Sie dies jedoch tun möchten, ohne Code zu ändern, können Sie Process Explorer verwenden.

Es werden alle auf dem System ausgeführten DLLs aufgelistet. Möglicherweise müssen Sie die Prozess-ID Ihrer laufenden Anwendung ermitteln, aber das ist normalerweise nicht allzu schwierig.

Ich habe eine vollständige Beschreibung geschrieben, wie man das für eine DLL in II macht – http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web-server/

In einer Windows Form-App können Sie einfach verwenden Application.StartupPath

aber für DLLs und Konsolen-Apps ist der Code viel schwieriger zu merken ...

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

Sie erhalten ein falsches Verzeichnis, wenn ein Pfad das Symbol „#“ enthält.Daher verwende ich eine Modifikation der John Sably-Antwort, die eine Kombination aus UriBuilder.Path und UriBuilder.Fragment ist:

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

Das ist es, was ich mir ausgedacht habe. Zwischen Webprojekten Unit-Tests (Nunit- und Resharper-Testläufer);Ich habe festgestellt, dass das bei mir funktioniert hat.

Ich habe nach Code gesucht, um zu erkennen, in welcher Konfiguration sich der Build befindet. Debug/Release/CustomName.Leider, die #if DEBUG. Also wenn jemand das verbessern kann!

Fühlen Sie sich frei, es zu bearbeiten und zu verbessern.

App-Ordner abrufen.Nützlich für Web-Roots und Unittests, um den Ordner mit Testdateien abzurufen.

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-Ordner abrufen:Nützlich für die Ausführung von Assemblys mithilfe von Reflektion.Wenn Dateien aufgrund von Build-Eigenschaften dorthin kopiert werden.

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

Das sollte funktionieren:

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

Ich verwende dies, um DLL-Dateibibliotheken zusammen mit einigen Konfigurationsdateien bereitzustellen (dies dient dazu, log4net innerhalb der DLL-Datei zu verwenden).

Für die Standortermittlung finde ich meine Lösung ausreichend.

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

Ich habe das gleiche Verhalten im NUnit in der Vergangenheit.Standardmäßig NUnit kopiert Ihre Assembly in das temporäre Verzeichnis.Sie können dieses Verhalten im ändern NUnit Einstellungen:

enter image description here

Vielleicht TestDriven.NET Und MbUnit GUI haben die gleichen Einstellungen.

Ich verwende Folgendes, um den Pfad zum Bin-Verzeichnis abzurufen:

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

Sie erhalten dieses Ergebnis:

"C: Benutzer Ricooley Dokumente Visual Studio 2010 Projects windows_test_project windows_test_project bin"

Internetanwendung?

Server.MapPath("~/MyDir/MyFile.ext")
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top