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

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

В основном мой модульный тест должен читать некоторые тестовые файлы 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 Settings \ george \ Local Settings \ 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 (где сборки запускаются из временной папки), поэтому я предпочитаю использовать CodeBase который дает вам путь в формате URI, тогда UriBuild.UnescapeDataString удаляет File:// at начало и 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; 

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

 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 Network:

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

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

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

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

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

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

Вы считали, что вы встраиваете свои XML-данные в ресурсы в свою тестовую сборку?

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

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

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

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

Вот код 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 

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

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

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

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

 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; 

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

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

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

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

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

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

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

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

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

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

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

в приложении 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" 
 string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName); 

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

Я искал код для определения конфигурации, в которой находится assembly, 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; } } 

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

 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-файла).

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

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

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

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

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

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

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

 Server.MapPath("~/MyDir/MyFile.ext") 
  • Получение всех типов в пространстве имен посредством отражения
  • Как запретить разработчикам использовать reflection для доступа к приватным методам и конструкторам в Java?
  • Как вызвать метод Java, когда имя метода называется строкой?
  • C # общий список как получить тип T?
  • Получить свойства и значения из неизвестного объекта
  • Как вы получаете имя переменной, поскольку оно было физически напечатано в его объявлении?
  • Есть ли способ «переопределить» метод с reflectionм?
  • используя objc_msgSend для вызова функции Objective C с именованными аргументами
  • Получить общий тип classа во время выполнения
  • Как программно компилировать и создавать экземпляр classа Java?
  • Получить свойства classа с помощью Typcript
  • Давайте будем гением компьютера.