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

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

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

Edit: Похоже, люди неправильно понимают, о чем я спрашиваю.

Моя тестовая библиотека находится, скажем, в каталоге

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:\Documents and Настройки\георгий\Локальный Settings\Temp\ ....\DaoTests.dll

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

Комментарии к вопросу (6)
Решение

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

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

На Ассамблеи.Местоположение иногда дает забавные результаты при использовании Нанит (где сборки выполняются из временной папки), поэтому я предпочитаю использовать кода, который дает вам путь в формате URI, то UriBuild.UnescapeDataString удаляет файл:// в начале и GetDirectoryName меняет его на нормальный формат Windows.

Комментарии (17)

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

//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 );
Комментарии (12)

Это's, как просто, как это:

var dir = AppDomain.CurrentDomain.BaseDirectory;
Комментарии (9)

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

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();
Комментарии (3)

Единственное решение, которое работает для меня, когда через codebase и сетевых общих папок UNC был:

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

Он также работает с нормальных ресурсов.

Комментарии (6)

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

string path = System.Reflection.Assembly.GetExecutingAssembly().Location
Комментарии (0)

Что по этому поводу:

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Комментарии (0)
AppDomain.CurrentDomain.BaseDirectory

работает с графическим MbUnit.

Комментарии (2)

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

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

Рассматривали ли вы внедрение XML-данных в качестве ресурсов внутри тестовой сборки?

Комментарии (1)

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

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

Это возвращает url (файл://). Вместо того, чтобы возиться с строковые манипуляции или UnescapeDataString, это может быть преобразовано с минимальными усилиями, используя LocalPath собственность Ури.

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
Комментарии (2)

Вот VB.NET порт Джон Циблы's код. В 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
Комментарии (1)
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
Комментарии (0)

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

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

Тогда просто отрезать то, что вам не нужно

Комментарии (0)

За все эти годы, никто на самом деле упоминал об этом. Трюк я узнал от крутые project ApprovalTests](https://github.com/approvals/ApprovalTests.Net/blob/master/ApprovalUtilities/Utilities/PathUtilities.cs). Хитрость заключается в том, что вы используете отладочную информацию в сборку, чтобы найти оригинальный каталог.

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

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

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;
Комментарии (3)

Я'вэ использовал сборку.Кода вместо местоположение:

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-адрес места, где этот файл был найден, в то время как расположение-это путь, где он был на самом деле заряжен. Например, если сборка была загружена из интернета, ее код может начинаться с "http://", но его расположение может начать с "C:\". Если файл был теневого копирования, расположение будет путь к копии файла в теневой копии реж. Это также хорошо знать, что кодовая база не гарантируется, комплект для сборки в GAC. Местоположение всегда будет вместе с Набор для сборки, загруженные с диска.&и quot;

Вы may хотите использовать кода, вместо местоположения.

Комментарии (2)

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

AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
Комментарии (1)

Вы можете получить бин пути Домен приложений.CurrentDomain.RelativeSearchPath

Комментарии (0)

в виде приложения Windows, вы можете просто использовать приложение.StartupPath`

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

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

root += slash;
string settingsIni = root + "settings.ini"
Комментарии (0)

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

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

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

Комментарии (2)