Как получить путь к сборке, в которой находится код?
есть ли способ получить путь для сборки, в которой находится текущий код? Мне не нужен путь вызывающей сборки, только тот, который содержит код.
В основном мой модульный тест должен прочитать некоторые тестовые файлы xml, которые расположены относительно dll. Я хочу, чтобы путь всегда разрешался правильно, независимо от того, выполняется ли тестовая dll TestDriven.NET, графический интерфейс MbUnit или что-то еще.
редактировать: люди, кажется, быть не понимаю, о чем я спрашиваю.
моя тестовая библиотека находится в say
C:projectsmyapplicationdaotestsbinDebugdaotests.dll файлы
и я хотел бы сделать этот путь:
C:projectsmyapplicationdaotestsbinDebug
три предложения до сих пор терпят неудачу, когда я бегу от Mbunit Gui:
Environment.CurrentDirectory
дает c:Program Файлы MbUnitSystem.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location
дает C:Documents и Настройкиgeorgeлокальный НастройкиTemp .... DaoTests.dll файлыSystem.Reflection.Assembly.GetExecutingAssembly().Location
дает то же самое, что и предыдущий.
26 ответов
Я определил следующее свойство, поскольку мы часто используем его в модульном тестировании.
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.
это поможет?
//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 );
то же самое, что и ответ Джона, но немного менее подробный метод расширения.
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, было:
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
Он также работает с обычными URIs тоже.
Это должно работать, если сборка не теневое копирование:
string path = System.Reflection.Assembly.GetExecutingAssembly().Location
Я подозреваю, что реальная проблема здесь в том, что ваш тестовый бегун копирует вашу сборку в другое место. Во время выполнения невозможно определить, откуда была скопирована сборка, но вы, вероятно, можете щелкнуть переключатель, чтобы сообщить тестовому бегуну запустить сборку оттуда, где она находится, а не копировать ее в теневой каталог.
такой переход, вероятно, будет отличаться для каждого теста, конечно.
рассматривали ли вы возможность внедрения XML-данных в качестве ресурсов внутри вашей тестовой сборки?
Как насчет этого:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
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 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 говорит:
"кодовая база-это URL-адрес места, где был найден файл, а местоположение-путь, по которому он был фактически загружен. Например, если сборка была загружена из интернета, Кодовая база может начинаться с " http://", но ее расположение может начинаться с"C:\". Если файл был скопирован тенью, то местом будет путь к копии файла в директории теневой копии. Также полезно знать, что кодовая база не гарантируется для сборок в GAC. Однако расположение всегда будет установлено для сборок, загружаемых с диска."
вы мая хотите использовать кодовую базу вместо местоположения.
за все эти годы, никто на самом деле упоминал об этом. Трюк, который я узнал от awesome проект ApprovalTests. Фокус в том, что вы используете отладочную информацию в сборке, чтобы найти исходный каталог.
это не будет работать в режиме выпуска, ни с включенной оптимизацией, ни на машине, отличной от той, на которой она была скомпилирована.
но это даст вам пути, которые являются относительно расположения файл исходного кода, который вы вызываете из
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-файл с build вы должны найти его.
или
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));
// The location of the Assembly
assembly.Location;
насколько я могу судить, большинство других ответов есть несколько проблем.
правильный способ сделать это для disk-based (в отличие от web-based), non-GACed assembly должен использовать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);
тогда просто отрежьте то, что вам не нужно
все предлагаемые ответы работают, когда разработчик может изменить код, чтобы включить необходимый фрагмент, но если вы хотите сделать это без изменения кода, Вы можете использовать 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"
вот что я придумал. между веб-проектами, модульными тестами (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;
}
}
Это должно работать:
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
GUI имеют те же настройки.
Я использую это, чтобы получить путь к каталогу bin:
var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i);
в результате:
"c:\users\ricooley\documents\visual студия 2010\проекты\Windows_Test_Project\Windows_Test_Project\bin"