Tuesday, July 31, 2007

Structuring .NET Windows Installations

How to structure the application installation directories and how the assemblies should be placed becomes much important when you have a suit of applications with several related apps. For this type of situations, it is very natural to have few core assemblies common for more than one app.

If you come from COM background, one immediate solution that come to mind may be to store in the GAC (Global Assembly Cache). But if you are coming from Java background (like me) then you may probably like to have your application to have minimum windows dependencies. The you would prefer a application which works simply when you copy the files to a destination folder. (still GAC has it's own share of advantages like assembly versioning)

If you want a non GAC solution, design your solution installation folder to support holding the common executables. You may have your installation structure as following:


Here all the executables are placed in the root installation directory and dependencies are placed in sub directories. Then in .config files you should specify the dependency probe paths:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Common_DLLs"/>
</assemblyBinding>
</runtime>
</configuration>

But what if you want a much more modular structure with every application having a separate directory but common dlls are located in a separate dir, then you may have the following structure

In this case, "<probing privatePath="Common_DLLs"/>" will not work as now the dependencies are not stored in a sub directory of your executables. You have to use "<codeBase/>" directive in your configuration files. One important thing to note is that you have to make your dependency assemblies strong named in this case. Have the following in your .config files.

<configuration>
<runtime>

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Common_DLL_1" culture="neutral" publicKeyToken="96c6ab020ca54674"/>
<codeBase version="1.0.0.0" href="..Common_DLLsCommon_DLL_1.dll"/>
</dependentAssembly>
<dependentAssembly>...</dependentAssembly>

</assemblyBinding>
</runtime> </configuration>

If I had to select between, I would prefer second approach to the first one as this allows me to better structure my solution installation. Also strong naming can help avoiding much of the bad 'dll hell' experiences.

There are more interesting stuff to discuss here such as how you manage common configurations (in .config files) across these related applications. For an example if all the applications are connecting to a common database, then how do we keep connection string in a single location is a problem to solve (If you do not want to store in the Windows Registry either). I'm hoping to discuss this on a separate post.

[tag: 99xt ]

No comments: