.netappdomainshadow-copyappdomainsetup

What is the right way to set shadow copying for the default AppDomain


Relating to Can I make the default AppDomain use shadow copies of certain assemblies?, it describes a working solution to activate shadow copying within the default AppDomain for a specific directory.

Basically it says to use these simple methods:

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

But because the methods used here are marked as obsolete I was wondering what is now the correct way to accomplish the same. The warning message hints to:

Please investigate the use of AppDomainSetup.ShadowCopyDirectories instead

An AppDomain has a member of this type called SetupInformation which might bring you to this straightforward implementation

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

Unfortunately this has no effect. So the question is, is there a way to alter the AppDomainSetup of the current appdomain to activate shadow copying ?


Solution

  • As far as I know these methods only work on .NET Framework version 1.1. For all later versions you cannot enable shadow-copying on the main AppDomain. You need to create a new AppDomain and set-it up appropriately. A simple approach is to create a loader application that simply:

    A good starting point can be found in the Shadow Copying of Applications CodeProject article. The following program is taken from the article with a slight modification (the cache path is not specified:

    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);
            }
        }
    }
    

    You will have to: