Как мне получить путь к сборке, в которой находится код? - PullRequest
719 голосов
/ 10 сентября 2008

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

В основном мой модульный тест должен прочитать некоторые тестовые файлы XML, которые расположены относительно DLL. Я хочу, чтобы путь всегда разрешался правильно, независимо от того, запускается ли dll-тестирование из TestDriven.NET, графический интерфейс 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 дает то же, что и предыдущий.

Ответы [ 27 ]

7 голосов
/ 10 сентября 2008
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
7 голосов
/ 19 мая 2009

Вот порт 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
6 голосов
/ 16 июня 2014

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

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

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

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
6 голосов
/ 10 сентября 2008

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

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;
6 голосов
/ 30 сентября 2015

За все эти годы никто не упоминал об этом. Уловка, которую я узнал от удивительного проекта 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;
    }
}
6 голосов
/ 10 сентября 2008

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

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

2 голосов
/ 22 апреля 2016

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

2 голосов
/ 17 сентября 2016

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

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

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

2 голосов
/ 11 декабря 2017

в приложении 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"
1 голос
/ 10 сентября 2008
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...