AppDomain shadow copying not working (original ass

2020-03-26 07:17发布

问题:

Here's a small class I'm using to probe for a list of available plugins:

internal static class PluginDirectoryLoader
{
    public static PluginInfo[] ListPlugins(string path)
    {
        var name = Path.GetFileName(path);
        var setup = new AppDomainSetup
        {
            ApplicationBase = path,
            ShadowCopyFiles = "true"
        };
        var appdomain = AppDomain.CreateDomain("PluginDirectoryLoader." + name, null, setup);
        var exts = (IServerExtensionDiscovery)appdomain.CreateInstanceAndUnwrap("ServerX.Common", "ServerX.Common.ServerExtensionDiscovery");
        PluginInfo[] plugins = null;
        try
        {
            plugins = exts.ListPlugins(); // <-- BREAK HERE
        }
        catch
        {
            // to do
        }
        finally
        {
            AppDomain.Unload(appdomain);
        }
        return plugins ?? new PluginInfo[0];
    }
}

The path parameter points to a subdirectory containing the plugin assemblies to load. The idea is to load them using a separate AppDomain with shadow copying enabled.

In this case, shadow copying isn't really necessary seeing as the AppDomain is unloaded quickly, but when I actually load the plugins in the next block of code I intend to write, I want to use shadow copying so the binaries can be updated on the fly. I have enabled shadow copying in this class as a test to make sure I'm doing it right.

Apparently I'm not doing it right because when I break in the debugger on the commented line in the code sample (i.e. plugins = exts.ListPlugins()), the original plugin assemblies are locked by the application!

Seeing as I'm specifying that assemblies loaded by the AppDomain should be shadow copied, why are they being locked by the application?

回答1:

I figured it out. There was one property I missed in AppDomainSetup. The property was ShadowCopyDirectories.

var setup = new AppDomainSetup
{
    ApplicationBase = path,
    ShadowCopyFiles = "true",
    ShadowCopyDirectories = path
};

When breaking on the line mentioned in my question, I can now delete the plugin assemblies even without unloading the AppDomain.