Skip to content
This repository has been archived by the owner. It is now read-only.

AppDomainAssemblyTypeScanner locks DLL files #2123

hassanselim0 opened this issue Nov 21, 2015 · 1 comment

AppDomainAssemblyTypeScanner locks DLL files #2123

hassanselim0 opened this issue Nov 21, 2015 · 1 comment


Copy link

hassanselim0 commented Nov 21, 2015

I'm using Nancy to make a small service that gets called from a main ASP.NET MVC application, during testing I have the self-host Nancy EXE and the main web app's DLLs in the same folder, and I noticed that I can't rebuild the web app while the EXE is still running because the DLL files are locked (in-use).
After digging around for a long time I found the problem to be in AppDomainAssemblyTypeScanner.LoadAssembliesWithNancyReferences where it calls Assembly.ReflectionOnlyLoadFrom which effectively locks the DLL files.
I've looked around on how to solve this, and discovered that you can't unload an assembly and you have to unload the whole AppDomain instead, I tried to create a new AppDomain just for the sake of the assembly inspection and called AppDomain.Load instead of Assembly.ReflectionOnlyLoadFrom then unloaded this temp AppDomain but that didn't work, it seems that AppDomain.Load also loads the assembly into the current AppDomain.
So after more searching around I found this:
It seems that in order to do this correctly the inspection code has to run completely under the new AppDomain and the results marshalled back to the main AppDomain.

Now I'm almost completely new to the concepts of AppDomains and Marshalling, I know the concepts but never implemented anything that touches these areas. I could try to implement this technique into ADATS but I feel I don't have the skills to do it correctly, I'm also worried that it might cause performance issues.
So I'm asking for your opinions about this. Did anybody here think of this before? If yes, then why didn't you implement this?

Copy link

smaclell commented Jan 13, 2016

This is not a problem with Nancy and more of an issue with how .NET is loading DLLs.

The easiest solution is to create another executable to wrap your original one. In the new application you then create a separate AppDomain with a feature called "Shadow Copy" enabled. This will copy DLLs to a separate directory before loading them. You local DLLs will be left unlocked.

The code for the wrapper executable looks like this:

using System;

class Program {
    static int Main( string[] args ) {

        AppDomainSetup setup = new AppDomainSetup {
            ShadowCopyFiles = "true" // This is key

        var domain = AppDomain.CreateDomain( "Real AppDomain", null, setup );

        // Execute your real application in the new app domain
        int result = domain.ExecuteAssembly(

        return result;


That is it! You do not need marshaling or anything fancy. For more information checkout this blog post I wrote about it. It has more code samples and links to a full solution.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
None yet
None yet

No branches or pull requests

3 participants