How to reorganize .dlls in your application

I have a .NET application that contains about 70 files. Application contains mostly .NET assemblies, but there are a few native .dlls as well. This application is deployed on multiple machines. Native .dlls never change and we do not build them when the application is compiled.

Usually, I deploy the application by wiping the old version (after I do a backup) and copy the new version into an empty directory. But here is a dilemma. If I copy native .dlls as part of the build process, it increases build time, as well as copy time. And because they never change it looks like a waste of time. But if I will skip them, then I cannot wipe a directory and copy everything because these .dlls will be missing and application will crash.

An obvious solution will be to put them in some specific directory (for example Bin) and use them from that directory. But in this case, I will have to change code everywhere to load Bin\Foo.dll instead of Foo.dll. It seems a simple task, but there are several places to change, and I wasn’t sure what name I will use at the end, so I decided to search for another solution. And the solution I found is relatively simple. Remember this is only for native .dlls. For .NET assemblies there is a different and much simpler solution.

Firstly, change .config file for your application and add windows section:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <windows>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Bin"/>
    </assemblyBinding>
  </windows>
</configuration>

This will state that the loader should check the Bin directory when searching for native assemblies. Next step is to give a manifest to a native .Dll. Let’s assume we have Foo.dll in a Bin directory. Create Foo.manifest in the same directory with following content:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" name="Foo" version="1.0.0.0"/>
  <file name="Foo.dll" />
</assembly>

We are almost there. Final thing is to give a manifest to the application itself. This step took most of my time because during build time, the application will get a manifest from a build tool or an IDE. So, there are few options. Simplest, is to point your IDE to a manifest you create. I recommend extracting a manifest from resources of your executable and then add data to it. In my case I had the console application, so I just pointed Visual Studio to my manifest in a Project Options in an Application tab, in Resources then Icon and Manifest. Manifest looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <dependency>
    <dependentAssembly>
      <assemblyIdentity name="Foo" version="1.0.0.0"/>
    </dependentAssembly>
  </dependency>
</assembly>

I repeat, you cannot use this manifest in a WinForms application, because it contains much more necessary information.

As you can see it is quite simple: application declares that it requires assembly with specific name, config file specifies where to search for assemblies and manifest files there provide name for each assembly.

I hope it helps someone.