Modifying .Net Assembly Search Order

how-to | home

Default search order

Topic Using .Net (CLR Managed) Classes in Win32 Applications described the default .Net assembly search order. The conclusion is that we have two locations where we can place COM-visible .Net assemblies:

An assembly located in the assembly-specific folder will find referenced .Net assemblies as long as they are located in GAC or in the application folder. Therefore if it does not have any non-global dependencies, this option will work. In this case the CLR manifest file may be a separate XML manifest file located in the application folder. As stated in the above topic, the CLR XML manifest file and the corresponding DLL may not be located in the same folder because .Net will only try the DLL and not the manifest if both are present in the folder.

An assembly located in the application folder will find all global dependencies as well as those in the application folder. However the manifest file must be embedded as #1 manifest resource. This is the default behavior or sxs32cmd /CLR: command. This avoids additional problems resulting from COM-visible assemblies referencing each other.

Changing the assembly search locations

It is possible to change the .Net assembly search order by changing the application configuration file. The application.exe.config file is accessed by .Net regardless of whether the main program is managed or not. The following configuration file will make .Net look for dependencies in the libraries subfolder of the application folder:

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="libraries"/>
    </assemblyBinding>
  </runtime>
</configuration>

With this change we can place all dependencies in the libraries folder. We can also place all COM-visible assemblies in the same folder. The corresponding Fusion log contains the following search entries:

LOG: Download of application configuration file was attempted from file:///C:/SxsExample/ExampleProgram.exe.Config.
LOG: Found application configuration file (C:\SxsExample\ExampleProgram.exe.Config).
LOG: Private path hint found in configuration file: libraries.
LOG: Using  application configuration file: C:\SxsExample\ExampleProgram.exe.Config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/SxsExample/classlibrary1.DLL.
LOG: Attempting download of new URL file:///C:/SxsExample/classlibrary1/classlibrary1.DLL.
LOG: Attempting download of new URL file:///C:/SxsExample/libraries/classlibrary1.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\SxsExample\libraries\classlibrary1.dll

Note that .Net first tries the standard locations: the application folder then the assembly-specific subdirectory. After both checks fail, .Net proceeds to the configured privatePath.

"privatePath" may contain a list of subfolders separated by semicolons. This allows organizing DLLs in logically designed tree of subfolders.

More information

See also Using CLR managed classes in unmanaged win32 applications

And Assembly Search Sequence Changes in Windows 7

Assembly search order Assembly Searching Sequence on MSDN

More on assembly directory structure Private Assemblies on MSDN

You may also wish to read Using .Net (CLR Managed) Classes in IIS6/IIS7

Excellent blog post by Junfeng Zhang Registration Free COM/.Net interop