如何正确地为默认的AppDomain设置影子复制?

9

关于我能否使默认AppDomain使用某些程序集的影子副本?,它描述了一种工作解决方案,可以在默认AppDomain中激活特定目录的影子复制。

基本上,它建议使用以下简单方法:

AppDomain.CurrentDomain.SetShadowCopyPath(aDirectory);
AppDomain.CurrentDomain.SetShadowCopyFiles();

但由于这里使用的方法被标记为过时,我想知道现在实现相同功能的正确方法。警告信息提示:

请调查使用AppDomainSetup.ShadowCopyDirectories的方法

一个AppDomain有一个名为SetupInformation的成员,这可能会带您到这个简单的实现。

AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories = aDirectory;
AppDomain.CurrentDomain.SetupInformation.ShadowCopyFiles = "true";

很遗憾,这没有任何效果。那么问题是,有没有一种方法可以更改当前应用程序域的AppDomainSetup以激活影子复制?


1
回答“很遗憾,这没有任何效果。”(我知道已经过去3年了),这是因为属性SetupInformation创建了内部FusionStore属性的克隆,而FusionStore属性本身是对用于初始化当前域的实际AppDomainSetup的引用。想法是,在初始化之后,这些属性不能再被修改(尽管我想知道为什么他们没有将它们设置为只读以表示这一点)。 - Abel
2个回答

16
据我所知,这些方法只适用于.NET Framework 1.1版本。对于所有后续版本,您无法在主AppDomain上启用影子复制。您需要创建一个新的AppDomain并进行适当设置。一个简单的方法是创建一个仅执行以下操作的加载器应用程序: 应用程序的影子复制 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 替换为您的应用程序配置文件的名称。如果您没有配置文件,则无需设置此项。

你可以在asp.net项目中实现这个。 - Andy Li

1

您不需要创建一个单独的应用程序。您可以在主方法中生成子域,或根据 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!
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接