Как правильно установить теневое копирование для домена приложения по умолчанию
Относительно Могу ли я заставить AppDomain по умолчанию использовать теневые копии определенных сборок?, он описывает рабочее решение для активации теневого копирования в AppDomain по умолчанию для определенного каталога.
В основном это говорит об использовании этих простых методов:
AppDomain.CurrentDomain.SetShadowCopyPath(aDirectory);
AppDomain.CurrentDomain.SetShadowCopyFiles();
Но поскольку используемые здесь методы помечены как устаревшие, мне было интересно, какой сейчас правильный способ добиться того же. Предупреждение предупреждает:
Пожалуйста, исследуйте использование AppDomainSetup.ShadowCopyDirectories вместо
Домен приложения имеет член этого типа, называемый SetupInformation
что может привести вас к этой простой реализации
AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories = aDirectory;
AppDomain.CurrentDomain.SetupInformation.ShadowCopyFiles = "true";
К сожалению, это не имеет никакого эффекта. Итак, вопрос в том, есть ли способ изменить AppDomainSetup текущего домена приложения, чтобы активировать теневое копирование?
2 ответа
Насколько я знаю, эти методы работают только на.NET Framework версии 1.1. Для всех более поздних версий нельзя включить теневое копирование на главном домене приложений. Вам нужно создать новый AppDomain
и настроить его соответствующим образом. Простой подход заключается в создании приложения-загрузчика, которое просто:
- Создает новый домен приложений с включенным теневым копированием. Для этого вам нужно будет использовать одну из перегрузок AppDomain.CreateDomain, которые принимают параметр AppDomainSetup.
- Выполняет ваше основное приложение, используя метод AppDomain.ExecuteAssembly.
Хорошую отправную точку можно найти в статье CodeProject по теневому копированию приложений. Следующая статья взята из статьи с небольшим изменением (путь кеша не указан:
using System;
using System.IO;
namespace Loader
{
static class Program
{
[LoaderOptimization(LoaderOptimization.MultiDomainHost)]
[STAThread]
static void Main()
{
/* Enable shadow copying */
// Get the startup path. Both assemblies (Loader and
// MyApplication) reside in the same directory:
string startupPath = Path.GetDirectoryName(
System.Reflection.Assembly
.GetExecutingAssembly().Location);
string configFile = Path.Combine(
startupPath,
"MyApplication.exe.config");
string assembly = Path.Combine(
startupPath,
"MyApplication.exe");
// Create the setup for the new domain:
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = "MyApplication";
setup.ShadowCopyFiles = "true"; // note: it isn't a bool
setup.ConfigurationFile = configFile;
// Create the application domain. The evidence of this
// running assembly is used for the new domain:
AppDomain domain = AppDomain.CreateDomain(
"MyApplication",
AppDomain.CurrentDomain.Evidence,
setup);
// Start MyApplication by executing the assembly:
domain.ExecuteAssembly(assembly);
// After the MyApplication has finished clean up:
AppDomain.Unload(domain);
}
}
}
Тебе придется:
- замещать
MyApplication.exe
с именем вашей исполняемой сборки. - замещать
MyApplication
с названием приложения. - замещать
MyApplication.exe.config
с именем файла конфигурации вашего приложения. Если у вас его нет, вам не нужно его устанавливать.
Вам не нужно создавать отдельное приложение. Вы можете просто создать поддомен в вашем методе main или вызвать метод main на основе AppDomain.CurrentDomain.IsDefaultAppDomain()
значение:
public static void Main(string[] args)
{
if (AppDomain.CurrentDomain.IsDefaultAppDomain())
{
// Loader
var entryPoint = System.Reflection.Assembly
.GetExecutingAssembly();
var applicationName = entryPoint.GetName().Name;
// Create the setup for the new domain:
var setup = new AppDomainSetup();
setup.ApplicationName = applicationName;
setup.ShadowCopyFiles = "true"; // note: it isn't a bool
// Create the application domain. The evidence of this
// running assembly is used for the new domain:
AppDomain domain = AppDomain.CreateDomain(
applicationName,
AppDomain.CurrentDomain.Evidence,
setup);
try
{
// Start MyApplication by executing the assembly:
domain.ExecuteAssembly(entryPoint.Location, args);
}
finally
{
// After the MyApplication has finished clean up:
AppDomain.Unload(domain);
}
}
else
{
// Main
ActualMain(args);
}
}
public static int ActualMain(string[] args)
{
//Hello-world!
}