Как получить путь сборки, в которой находится код?

Есть ли способ получить путь для сборки, в которой находится текущий код? Мне не нужен путь вызывающей сборки, только тот, который содержит код.

В принципе, мой unit test должен читать некоторые тестовые файлы xml, которые расположены относительно dll. Я хочу, чтобы путь всегда корректно решался независимо от того, запускается ли тестовая dll из TestDriven.NET, GUI MbUnit или чего-то еще.

Изменить. Люди, похоже, неправильно понимают, что я прошу.

Моя тестовая библиотека находится в разделе

C:\Проекты\MyApplication\daotests\Bin\Debug\daotests.dll

и я хотел бы получить этот путь:

C:\Проекты\MyApplication\daotests\Bin\Debug\

Три предложения до сих пор не сработают, когда я бегу от MbUnit Gui:

  • Environment.CurrentDirectory дает c:\Program Files\MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location дает C:\Documents and Настройки\джордж\Local Настройки \Temp \....\DaoTests.dll

  • System.Reflection.Assembly.GetExecutingAssembly().Location дает то же самое, что и предыдущее.

Ответ 1

Я определил следующее свойство, поскольку это часто используется при модульном тестировании.

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.

Ответ 2

Помогает ли это?

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

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

Ответ 3

Это так просто:

var dir = AppDomain.CurrentDomain.BaseDirectory;

Ответ 4

То же, что и ответ Джона, но немного менее подробный метод расширения.

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

Ответ 5

Единственное решение, которое работало для меня при использовании общих ресурсов CodeBase и UNC Network:

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

Он также работает с обычными URI.

Ответ 6

Это должно работать, если сборка не скопирована теневой копией:

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

Ответ 7

Как насчет этого:

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

Ответ 8

AppDomain.CurrentDomain.BaseDirectory

работает с GUI MbUnit.

Ответ 9

Я подозреваю, что настоящая проблема заключается в том, что ваш тестовый бегун копирует вашу сборку в другое место. Во время выполнения нет возможности указать, откуда была скопирована сборка, но вы, вероятно, можете переключить переключатель, чтобы сообщить тестовому бегуну, что он запускает сборку, где он есть, и не копировать его в теневой каталог.

Такой переключатель, вероятно, будет отличаться для каждого тестируемого, конечно.

Рассматривали ли вы возможность встраивания ваших XML-данных в ресурсы в тестовую сборку?

Ответ 10

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

Ответ 11

Вот порт 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

Ответ 12

Насколько я могу судить, большинство других ответов имеют несколько проблем.

Правильный способ сделать это для дисковой (в отличие от веб-) сборки, отличной от GACed, использовать выполняемое в настоящее время свойство сборки CodeBase.

Возвращает URL-адрес (file://). Вместо того, чтобы возиться с строковыми манипуляциями или UnescapeDataString, это можно преобразовать с минимальной суетой, используя LocalPath свойство Uri.

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

Ответ 13

Как насчет этого...

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

Затем просто взломайте то, что вам не нужно

Ответ 14

Текущий каталог, в котором вы находитесь.

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;

Ответ 15

Я использовал Assembly.CodeBase вместо Location:

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:\". Если файл был скопирован с тэпом, то Location будет путь к копии файла в директории shadow copy. Также хорошо знать, что CodeBase не гарантируется для сборок в GAC. Однако расположение всегда будет установлено для сборок, загруженных с диска.

Возможно, вы захотите использовать CodeBase вместо Location.

Ответ 16

За все эти годы никто не упомянул об этом. Трюк, который я узнал из удивительного проекта ApprovedTests. Фокус в том, что вы используете информацию об отладке в сборке, чтобы найти исходный каталог.

Это не будет работать в режиме 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;
    }
}

Ответ 17

Вы можете получить путь к bin   AppDomain.CurrentDomain.RelativeSearchPath

Ответ 18

Все предлагаемые ответы работают, когда разработчик может изменить код, чтобы включить требуемый фрагмент, но если вы хотите сделать это без изменения кода, вы можете использовать Process Explorer.

Он отобразит все исполняемые DLL в системе, вам может потребоваться определить идентификатор процесса для вашего запущенного приложения, но это обычно не так сложно.

Я написал полное описание того, как это сделать для dll внутри II - http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web-server/

Ответ 19

в приложении Windows Form вы можете просто использовать Application.StartupPath

но для библиотек DLL и консольных приложений запоминать код гораздо сложнее...

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

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

Ответ 20

Я считаю, что это будет работать для любого приложения:

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

Ответ 21

string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);

Ответ 22

Вы получите неправильный каталог, если путь содержит символ "#". Поэтому я использую модификацию ответа Джона Сибли, которая представляет собой комбинацию UriBuilder.Path и UriBuilder.Fragment:

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

Ответ 23

Это должно работать:

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 вместе с некоторым конфигурационным файлом (это нужно использовать log4net из DLL файла).

Ответ 24

Вот что я придумал. Между веб-проектами, модульные тесты (nunit и resharper test runner); Я нашел, что это сработало для меня.

Я искал код для определения конфигурации, в которой находится сборка, Debug/Release/CustomName. Увы, #if DEBUG. Поэтому, если кто-то может улучшить это!

Не стесняйтесь редактировать и улучшать.

Получение папки приложения. Полезно для веб-корней, unittests, чтобы получить папку тестовых файлов.

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

Ответ 25

Я нахожу свое решение подходящим для поиска местоположения.

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

Ответ 26

В прошлом я имел такое же поведение в NUnit. По умолчанию NUnit копирует вашу сборку в каталог temp. Вы можете изменить это поведение в настройках NUnit:

введите описание изображения здесь

Возможно, TestDriven.NET и MbUnit GUI имеют одинаковые настройки.

Ответ 27

Я использую это, чтобы получить путь к 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"

Ответ 28

Веб-приложение?

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