16

Say we have an application which consists of one executable and 5 libraries. Regularly all of these will be contained in one directory and the libraries will be loaded from there.

Is it possible to do so that I can have for example some of the libraries in one directory called Lib, and the rest in one called Lib2? So that the application directory would only contain the executable itself and the other assemblies would be contained in various logical directories.

How can I do this? And I would like to know how to do the loading of the assemblies, but also how to make the building of the application put the assemblies in the right directory.

Svish
  • 152,914
  • 173
  • 462
  • 620
  • Yes, you can, per DotNetWill's answer. But there is little to gain and you may run into a lot of maintenance problems. – H H Oct 20 '09 at 12:42

4 Answers4

32

You can add additional search paths to your app.config that it looks in to load assemblies. For example

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <probing privatePath="lib;thirdParty" />
  </assemblyBinding>
</runtime>

You can see more details here.

Bruno Brant
  • 8,226
  • 7
  • 45
  • 90
  • Fantastic. If you wanted more paths, would you add another `` tag, or would you add another `` with another `` tag? – Svish Oct 20 '09 at 12:30
  • Also, is there a way to add this path at runtime? For example if it was built up by using some sort of environment variables or other stuff. – Svish Oct 20 '09 at 12:31
  • 1
    Yup just add more. I don't think you can do it at runtime in .Net 2.0+, might be wrong there though. –  Oct 20 '09 at 12:34
  • @Svish you don't add more probing elements; Instead, add more directories separated by semicolons. (https://msdn.microsoft.com/en-us/library/823z9h8w%28v=vs.110%29.aspx). I've updated the answer to include those details. – Bruno Brant May 09 '15 at 18:15
13

If you want to manually manage where to get assembles from, you have two possibilities:

  1. Handle the AppDomain.AssemblyResolve event (as it is described by SLaks). Here is the code snippet:

    static void Main(string[] args)
    {
       ...
       AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
       ...
    }
    
    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
       string assembliesDir = "your_directory";
       Assembly asm = Assembly.LoadFrom(Path.Combine(assembliesDir, args.Name + ".dll"));
       return asm;
    }
    
  2. Create a domain with your own settings (by setting ApplicationBase or PrivateBinPath properties of the AppDomainSetup object).

So if you want to continue working in current domain you have to use method 1.

Vlad
  • 35,022
  • 6
  • 77
  • 199
Ilya Serbis
  • 21,149
  • 6
  • 87
  • 74
  • thank you! you just saved me, was googling for a solution like that, but found nothing in answers to other questions. This made my day :) – SwissCoder Jul 11 '12 at 11:10
  • I am trying to load an assembly using Assembly.Load which is not in GAC , which fails and AssemblyResolve event will be fired , where I am using LoadFrom to load it from a path. Now this assembly will be loaded in load context , so Does it use now Ngen 'ed images? thanks for any help – Paritosh Jan 20 '15 at 08:44
2

To make automatically copy the assemblies to the folder you want them to be in, you could set Copy Local to true for all of the references, and make a post-build step to move them into subdirectories.

Alternatively, you could set Copy Local to false, and add the referenced DLL files as files in the project in the appropriate subdirectories, and set Build Action to Copy to output directory (This will preserve subdirectories)

The most flexible way to make the runtime find them is to handle the AppDomain.AssemblyResolve event and manually load the assembly using Assembly.LoadFile. You would need some way for your code to know which assemblies are in which directories.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • That AssemblyResolve thing could probably be very helpful indeed. Didn't really know about that one. On the matter of the build stuff, what would you say is the cleanest solution to that? I think they both seem kind of messy, but I haven't really tried any of them so I don't really have a clue :p – Svish Oct 20 '09 at 13:47
  • If your are using runtime references, then copy to local wouldnt help. i.e. if you are using interface developments, the plugin modules are only available at runtime and design time references wont work in this context – Krishna Jan 14 '13 at 15:53
0

In your comment you mention adding paths and locations at runtime. Yes you can, but you have to use Assembly.Load(), and possibly reflection.

C. Ross
  • 31,137
  • 42
  • 147
  • 238