Есть ли способ получить путь к сборке, в которой находится текущий код? Мне не нужен путь к вызывающей сборке, только тот, который содержит код.
В основном мой модульный тест должен читать некоторые тестовые файлы xml, которые расположены относительно dll. Я хочу, чтобы путь всегда разрешался правильно, независимо от того, запускается ли тестовая dll из TestDriven.NET, графического интерфейса MbUnit или чего-то еще.
Редактировать: Люди, кажется, неправильно понимают, о чем я спрашиваю.
Моя тестовая библиотека находится, скажем,
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 и
Настройки \ george \ Local
Настройки \ Temp \ .... \ DaoTests.dll
System.Reflection.Assembly.GetExecutingAssembly().Location
дает то же, что и предыдущий.
Это должно быть приемлемое решение. AppDomain.CurrentDomain.BaseDirectory - правильный подход.
См. Также: поиск-мой-основной-исполняемый-путь-использование-сборки-против-приложения
Я пришел сюда в поисках решения для пакета nuget для чтения файла JSON из его каталога pacakge. Похоже, что когда выполняется пакет nuget, «AppDomain.CurrentDomain.BaseDirectory» указывает на каталог запущенных проектов, а не на каталог пакета nuget. Кажется, что ни один из них не нацелен на каталог пакета nuget правильно.
@ Лукас, нет, это не так, потому что этот вопрос был не об этом (на самом деле, когда его спросили, nuget не существовало) - не стесняйтесь начинать новый вопрос и пинговать меня там, но я могу сказать вам прямо сейчас, что в большинстве случаев это невозможно. Для большинства проектов каталог nuget - packages рядом с файлом sln. НО, когда вы компилируете и распространяете вещи, нет файла sln и каталога пакетов. Во время компиляции все необходимое (но не все) копируется в каталог bin. Лучше всего использовать сценарий postbuild, чтобы скопировать нужный файл.
Для тех, кто читает эти комментарии, полагая, что AppDomain.CurrentDomain.BaseDirectory - правильное решение, обратитесь к этот комментарий, который предлагает лучшее решение.





Это должно работать, если только сборка не тень скопирована:
string path = System.Reflection.Assembly.GetExecutingAssembly().Location
Текущий каталог, в котором вы существуете.
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;
это будет проблематично, если сборка была тень скопирована.
+1520! Environment.CurrentDirectory работает, если вы используете отражение в классе задач MSBuild, где исполняемая сборка находится в GAC, а ваш код находится в другом месте.
В общем, CurrentDirectory не сообщает вам, где находятся ваши исполняемые файлы. Это не то, для чего он используется. Просто часто случается, что исполняемые файлы находятся в одном и том же месте, поэтому многие программисты не понимают разницы. Затем они создают проблемы для некоторых конечных пользователей, которые ожидали, что приложение понимает правильное использование CurrentDirectory.
Это помогает?
//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 );
см. мою правку, это не так, это что-то странное в том, как работает MbUnit?
Почему? fullPath будет "C: \ projects \ myapplication \ daotests \ bin \ Debug \ daotests.dll", каталог будет "C: \ projects \ myapplication \ daotests \ bin \ Debug" Разве вы не этого хотите?
Ах, нет, я тебя понял. MSTest делает то же самое - каждый раз все копируется в новый временный каталог.
Задайте файлы xml как содержимое, скопированные с dll или ресурсы, прочитанные из dll.
Или просто typeof(DaoTests).Assembly
Я бы лично выбрал такой метод: public static string GetAssemblyDirectory<T>(){return System.IO.Path.GetDirectoryName(typeof(T).Assembly.Location);}
@JohnySkovdal - зачем использовать общий, если тип возврата всегда string, а вход всегда Type? Вы можете сделать: public static string GetAssemblyDirectory(this Type input){return System.IO.Path.GetDirectoryName(input.Assembly.Location);}, так что вам не нужно явно знать тип: unknown.GetType().GetAssemblyDirectory();
@Keith - я просто заменяю входной параметр параметром типа, поэтому мне не придется вызывать typeof, как вы это делаете в своем примере. Что касается того, что тип явно не нужен, у меня еще не было необходимости, поэтому у меня нет перегрузки, которая принимает System.Type в качестве входных данных (пока).
@SLaks @JohnySkovdal @Keith: Привет, ребята, используйте Assembly.GetExecutingAssembly(). Это "получает сборку, содержащую код, который выполняется в данный момент" (из описания метода). Я использую это в моей надстройке "EntitiesToDTOs". См. Реальный пример AssemblyHelper.cs.
Возникла проблема с сообщением @John Silby, так как он не выглядит так, как будто он работает для путей UNC ... например. \\ Сервер \ Папка \ File.ext. Этот сработал. +1
@FabianFernandez, посмотрите на вопрос еще раз, это не то, что здесь нужно, и это уже упоминалось как неработающее решение.
Да, я рассмотрел вопрос, и вы правы, похоже, я не заметил этого, когда увидел вопрос в первый раз. Мое плохое, спасибо!
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
Я подозреваю, что настоящая проблема здесь в том, что ваш тестовый исполнитель копирует вашу сборку в другое место. Во время выполнения невозможно определить, откуда была скопирована сборка, но вы, вероятно, можете щелкнуть переключателем, чтобы указать тестирующему исполнителю запустить сборку с того места, где она находится, а не копировать ее в теневой каталог.
Конечно, такой переключатель может быть разным для каждого участника тестирования.
Рассматривали ли вы возможность встраивания XML-данных в качестве ресурсов в тестовую сборку?
+1 за указание на проблему с теневым копированием. Однако по Assembly.CodeBase действительно можно определить исходное место.
Как насчет этого:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);
Я использовал 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: // » , но его Location может начинаться с "C: \". Если файл был теневым копированием, Location будет путь к копии файла в каталоге теневых копий. Также полезно знать, что установка CodeBase для сборок в GAC не гарантируется. Однако расположение всегда будет установлено для сборок, загружаемых с диска. "
Вы май хотите использовать CodeBase вместо Location.
@Kiquenet: Так много кода только для преобразования URI в путь. Конечно, это можно улучшить. Посмотрите на ответ Майка Шалла или SoMoS. Вы не должны пытаться преобразовать URI на строковом уровне, вместо этого используйте подходящие объекты. Хорошо, также неуклюже, что Assembly.CodeBase возвращает строку вместо более подходящего объекта, такого как URI или FileInfo.
Я определил следующее свойство, поскольку мы часто используем его в модульном тестировании.
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.
Я столкнулся с одной проблемой: если имя вашего каталога: c: \ My% 20Directory, то Uri.UnescapeDataString вернет: c: \ My Directory. Это означает, что File.Exists ("c: \ My Directory \ MyFile.txt ") вернет false, поскольку на самом деле правильный путь - это" c: \ My% 20Directory \ MyFile.txt "Я столкнулся с этим, поскольку в наших путях SVN есть пробелы, и когда мы их проверяем, он кодирует пробелы.
черт возьми, это все еще не работает для меня: 0 (Теперь вместо того, чтобы дать мне путь к MSBuild, я получаю путь к TeamCity C: \ TeamCity \ buildAgent \ temp \ buildTmp \ SYSTEM_SVR1 2010-08-24 17_34_23 \ Out, но еще один способ получить путь :-)
@John Sible: возвращает путь к исполняемой сборке, а не к сборке (как в .dll), которая загружается вызывающим исполняемым файлом. Мне нужен .dll, чтобы установить рабочий каталог. +1 хотя за полезный ответ и хорошую отправную точку.
Будьте осторожны при использовании этого параметра для проверки File.Exist (), поскольку этот метод вернет false на пути UNC. Вместо этого используйте ответ @Keith.
Не знал, что можно поставить статику перед публикой. Приятно знать, и я думаю, что предпочитаю удобочитаемость
Для людей, которым необходимо знать, сборка находится в System.Reflection, а путь - в System.IO. :)
Примечание: это не работает с сетевыми местоположениями (например, \\ REMOT_EPC \ Folder)
Обратите внимание, что вторая строка вызовет CA2234. Передайте новый Uri (codeBase) конструктору UriBuilder, чтобы исправить предупреждение.
@Jedidja Какую версию Visual Studio вы используете, вызывая ошибку? Просто попробовал в VS2012, и вроде нормально
@JohnSible 2012, хотя через msbuild в командной строке. Если вы посмотрите на включенные правила, проверено ли 2234? Я не уверен, что это один из минимально рекомендованных значений по умолчанию.
Также это не сработает, если в справочнике есть знаки "#". Числовые знаки разрешены в именах каталогов и файлов в Windows.
CodeBase - это беспорядок. Вот мой взгляд на это: stackoverflow.com/a/28319367/321013
Я полагался на этот метод в течение многих лет, но сегодня он потерпел неудачу, когда путь к каталогу, о котором идет речь, содержал '#'.
Это работает так же и кажется короче: string path = new Uri (Assembly.GetExecutingAssembly (). CodeBase) .LocalPath; return Path.GetDirectoryName (путь);
Это не поддается проверке ... Все ваши модульные тесты, которые проверяют этот код, завершатся ошибкой! см. ответ @Jalal
Мы долгое время использовали CodeBase, а теперь перешли на .Net45. Поведение CodeBase изменилось, поэтому он больше не возвращает каталог. Не используйте .CodeBase, если вы используете более новые версии DotNet! Теперь мы используем AppDomain.CurrentDomain.BaseDirectory, который правильно работает для любой версии DotNet.
Я считаю, что решение из моего ответа ниже stackoverflow.com/a/58051383/1671558 должно охватывать все варианты использования и довольно простое. Другой пользователь сообщил, что он работает практически везде, включая консоль, Интернет, модульные тесты.
Вот порт 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
То же, что и ответ Джона, но чуть менее подробный метод расширения.
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();
Вы имели ввиду assembly вместо Assembly.GetExecutingAssembly()?
Как отмечает Чувак, вы подали аргумент и не смогли его использовать.
Этот ответ просто неверен для рассматриваемого вопроса. Измененная версия этого ответа может дать вам путь к данной сборке. Однако здесь мы специально ищем выполняющуюся сборку, поэтому передача сборки не имеет смысла. Метод расширения - неподходящий инструмент для работы.
Это так просто:
var dir = AppDomain.CurrentDomain.BaseDirectory;
Это должно быть приемлемое решение. AppDomain.CurrentDomain.BaseDirectory - правильный подход.
спасибо, что вернули мое внимание к этому - не уверен, было ли это доступно в то время, когда я задавал вопрос, но это сейчас.
Нет, это не так. Это возвращает путь ОРИГИНАЛЬНОЙ ТОЧКИ ВХОДА, а не текущий исполняемый код. Если вы загрузили сборку вручную с другого пути или если она была загружена из GAC, она вернет неверный результат. Ответ правильный: stackoverflow.com/a/283917/243557 Быстрее по-прежнему Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).
На самом деле это не будет работать в веб-приложениях, но, насколько я понял, следующее дополнение должно работать для любого типа приложений: AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
Илье Черномордику. Для веб-приложений я использую: System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPat h
Это отлично подходит для модульного тестирования, если вы просто хотите получить исходный путь к контейнеру вашей тестовой сборки (скажем, для доступа к файлам вспомогательных данных в подпапках). Тестовая сборка - это точка входа в ваш код.
@IlyaChernomordik Я считаю, что ваше решение охватывает большинство сценариев - любой сценарий, с которым я столкнулся, в отличие от любого другого ответа. Он заслуживает большей наглядности. Вы определенно можете опубликовать это как отдельный ответ.
Отправили ответ, который, кажется, работает для любого приложения: stackoverflow.com/a/58051383/1671558l, как предложил @Timo
AppDomain.CurrentDomain.BaseDirectory
работает с графическим интерфейсом MbUnit.
Это отлично подходит для записи файла относительно корневого каталога в веб-приложении asp.net.
Я обнаружил, что этот в целом работает лучше всего. Выберите его, если не уверены.
Я использую это, чтобы получить путь к каталогу Bin:
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"
Я не вижу причин избегать здесь Path.getDirectoryName
@MaxKeller Если вы не видите причин, это не значит, что это правильно. Этот альтернативный метод Path.GetDirectoryName в десять раз быстрее.
Единственное решение, которое сработало для меня при использовании общих ресурсов CodeBase и UNC Network, было:
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
Он также работает с обычными URI.
Это должен быть принятый ответ. Действительно раздражает, что кодовая база по умолчанию неправильно обрабатывает UNC-ресурсы.
Это вылетает, когда в папке есть пробелы и черт знает какие еще символы ...
Я много использовал это и нашел сценарий один, в котором он не работает: если эта строка кода сама является частью пакета NuGet, который затем используется приложением! Мы также можем поддержать этот сценарий, заменив GetExecutingAssembly() на GetCallingAssembly().
@Timo: вы проверили, есть ли у этого изменения побочные эффекты? Если да, отредактируйте ответ, включив исправление.
@IgnacioSolerGarcia К сожалению, я должен сообщить, что он работал только на один уровень, т.е. он терпит неудачу, если пакет NuGet был вызван другим пакетом NuGet! Я сейчас использую это (из комментария Черномордика к этой странице): AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory. Первая часть предназначена для веб-приложений, а вторая - для других приложений.
Это должно работать:
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).
Для чего здесь используется fileMap?
Вот что я придумал. Между веб-проектами, модульные тесты (средство запуска тестов nunit и resharper); Я обнаружил, что это сработало для меня.
Я искал код, чтобы определить, в какой конфигурации находится сборка, Debug/Release/CustomName. Увы, но #if DEBUG. Так что, если кто-то может это улучшить!
Не стесняйтесь редактировать и улучшать.
Получение папки приложения. Полезно для веб-корней, юнит-тестов для получения папки с тестовыми файлами.
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;
}
}
Насколько я могу судить, у большинства других ответов есть несколько проблем.
Правильный способ сделать это для дисковая (в отличие от веб-), сборка без GAC - использовать свойство CodeBase исполняемой в данный момент сборки.
Это возвращает URL-адрес (file://). Вместо того, чтобы возиться с манипуляции со строками или UnescapeDataString, это можно преобразовать с минимальными усилиями, используя свойство LocalPathUri.
var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
Не работает, если путь содержит # (EscapedCodeBase работает, но EscapedCodeBase не работает, если путь содержит, например, %20 дословно (что является допустимой последовательностью символов в пути Windows)
Если мы хотим иметь этот код в пакете NuGet, мы можем исправить этот сценарий, заменив GetExecutingAssembly() на GetCallingAssembly().
Веб приложение?
Server.MapPath("~/MyDir/MyFile.ext")
@christiandev, это ответ, но может показаться, что это ответ на неправильный вопрос. Из вопроса довольно ясно, что это не веб-приложение, а сборка, запускаемая с помощью MbUnit. При этом ответ все еще не совсем правильный из-за теневого копирования Asp.Net (хотя, возможно, это может быть то, что ищет кто-то, ответивший на этот вопрос).
Я считаю, что мое решение подходит для определения местоположения.
var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;
Это уже один из самых популярных ответов. и явно упоминается в вопросе как нечто, что не работает в этой ситуации.
Приношу извинения за то, что пропустил это! Очевидно, я не дочитал до конца.
За все эти годы об этом никто не упомянул. Трюк, который я узнал из классного Проект 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;
}
}
Вы можете получить путь к корзине с помощью AppDomain.CurrentDomain.RelativeSearchPath
Как насчет этого ...
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/
Обратите внимание, что, во-первых, код в статье в значительной степени ориентирован на IIS, а во-вторых, он дает вам (я считаю) все библиотеки dll в настоящее время загружен, а не то, что выполняется одновременно.
Приведенный пример относится к iis, но те же шаги применимы, если dll выполняется в процессе вне iis. Это просто вопрос идентификации идентификатора процесса. Я обновлю статью, чтобы отметить это. Спасибо за предложение.
в приложении 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"
Вы получите неверный каталог, если путь содержит символ '#'. Поэтому я использую модификацию ответа Джона Сибли, которая представляет собой комбинацию 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);
}
}
Я считаю, что это сработает для любого приложения:
AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
Мои эксперименты показывают, что это наиболее надежный ответ, охватывающий не только веб-приложения и консольные приложения, но также вызовы из модульных тестов и пакетов NuGet (вложенных в любой уровень рекурсии).
Спасибо за это элегантное решение!
Начиная с .net framework 4.6 / .net core 1.0, теперь существует AppContext.BaseDirectory, который должен давать тот же результат, что и AppDomain.CurrentDomain.BaseDirectory, за исключением того, что домены приложений не были частью стандартного API 1.x .net core 1.x /.net.
AppContext.BaseDirectory
Для ASP.Net это не работает. Я нашел более подходящее решение на Почему AppDomain.CurrentDomain.BaseDirectory не содержит «bin» в приложении asp.net?. Он работает как для приложения Win, так и для веб-приложения ASP.Net.
public string ApplicationPath
{
get
{
if (String.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath))
{
return AppDomain.CurrentDomain.BaseDirectory; //exe folder for WinForms, Consoles, Windows Services
}
else
{
return AppDomain.CurrentDomain.RelativeSearchPath; //bin folder for Web Apps
}
}
}
Это ваше решение: var dir = AppDomain.CurrentDomain.BaseDirectory;