40

Let's suppose I have a Window Forms / Console Application C# project with some external references and references to other class library projects in the same solution too.

When I build the Window Form project, I want the referenced libraries be stored in a different location (eg: bin\Release\Libraries), and not in the same folder as the .exe.

Is it possible to do?

Oscar Mederos
  • 29,016
  • 22
  • 84
  • 124
  • 1
    Are you referencing them as a file reference, or a project reference? – mellamokb Feb 24 '11 at 21:19
  • 1
    with a postbuild step but you also have to change your AppDomainSetup to set the probing path for assemblies otherwise your Library dll's will never load. Have you thought of that? – rene Feb 24 '11 at 21:19
  • @mellamokb both. I have references to projects in my solution, and those (and the WinForm too) have references to external .dll files too. – Oscar Mederos Feb 24 '11 at 21:20
  • The main thing here is WHY you want to do this ? What is the benefit of having DLLs under Libraries subfolder ? – pero Feb 24 '11 at 21:40
  • 6
    @Petar That's what I usually do when deploying the deliverables of my applications, and I think having a `.exe` alone with *docs*, *license file*, etc. is much cleaner than having the `.exe` file and 5-10 `.dll` files in the same folder (in this case: deploying = just ziping the files) – Oscar Mederos Feb 24 '11 at 21:54
  • If you use CopyLocal=true then every rebuild copies many DLLs many times. Try to see how many times some DLL is replicated in you solution folder and subfolders. The same is if you are coping DLLs in postbuild. This slows you down as every build project is slowed by disk I/O. You can solve this by setting every project to build to some shared folder and by referencing DLLs instead of using project references (you will have to manage dependencies by hand). – pero Feb 24 '11 at 22:09
  • So, you are trading speed vs. having DLLs organized the same as in production. – pero Feb 24 '11 at 22:09
  • If your solution is very small and you have SSD then disk I/O is not problem for you. – pero Feb 24 '11 at 22:10

5 Answers5

18

There are 2 parts of your question:

How to configure solutions to build assemblies/EXE into folders of your choice - this is configured through properties of the project in VS (project properties -> build -> output path). Also value of check "copy local" property on each reference.

How to load assemblies files from non-default locations (i.e. from your ...\Libraries folder) - you need to make changes to your app.config file to add this non-default paths to assembly search location..

Link to Microsoft site no longer works, so summary from wayback machine: How to load an assembly at runtime that is located in a folder that is not the bin folder of the application:

Method 1: Install the assembly in the global assembly cache (GAC). The GAC is a computer-wide code cache where the common language runtime is installed. The GAC stores assemblies that you specifically designate to be shared by several applications.

Note You can only install strong-named assemblies in the GAC.

Method 2: Use an application configuration (.config) file with the tags A .config file contains the following settings:

• Settings that are specific to an application

• Settings that the common language runtime reads, such as the assembly binding policy settings and the remoting objects settings

• Settings that the application reads

The <codeBase> tags specify where the common language runtime can find an assembly. The common language runtime applies the settings of the <codeBase> tags from the .config file. The settings of the <codeBase> tags determine the version and the location of the assembly.

Method 3: Use the AssemblyResolve event The AssemblyResolve event fires whenever the common language runtime tries to bind to an assembly and fails. You can use the AddHandler method to add an event handler to the application that returns the correct assembly whenever the AssemblyResolve event fires.

The AssemblyResolve event handler must return an [Assembly] object, and the common language runtime must bind to this object. Typically, you can use the Assembly.LoadFrom method to load the assembly and then to return the object.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 5
    Further to the 2nd part of this answer, also look into the `` `.config` element - it allows you to specify other (sub) directories to search for assemblies – Basic Feb 24 '11 at 21:25
9

Correct answers were given earlier. I'll just mention that there is a nuget package for this called PrettyBin.

Install it on your startup project. DLLs and XMLs will go to a lib folder and you'll have a working example of how it's done, if you won't to customize.

Andrey Ershov
  • 1,773
  • 1
  • 16
  • 26
  • The easiest solution so far that just works! Thank you! – mandarin Jun 18 '15 at 09:26
  • 1
    I have post-build events that copy the contents of my build directory into a .zip. These post-build events seem to run before PrettyBin does its 'cleaning'. Do you know how I can get PrettyBin to run before post-build events? – jenovachild Oct 12 '16 at 01:53
  • 1
    @jenovachild It is probably not relevant anymore, but in case somebody is still wondering: PrettyBin only adds an extra After Build step to .csproj file. If you need to run it before/after some specific file, just unload your project, open .csproj file and modify the order of AfterBuild events. – Kajiyama Mar 10 '18 at 03:34
1

Set Reference path in project peoperties.

You can also specify where your compiled exe goes by specifying Output path in project peoperties.

ukhardy
  • 2,084
  • 1
  • 13
  • 12
1

You'll find best practices for organizing project references here: http://codebetter.com/patricksmacchia/2009/01/11/lessons-learned-from-the-nunit-code-base/

Look under chapter "The VisualStudio Project Reference + Copy Local true option is evil!"

pero
  • 4,169
  • 26
  • 27
  • Quote from the referenced page: "the assembly nunit.core.dll is duplicated 21 times while compiling the NUnit solution with VisualStudio! It means that it has to be copied/loaded/parsed 21 times by the C# compiler that apparently doesn’t come with a cache/hashCode optimization for such a case." but also "And indeed, the code of NUnit is pretty well layered. This is the result of the initial decision to create plenty of assemblies." So, basically having plenty of assemblies guides towards better code at the expense of compile time. Not such a bad deal. – Stéphane Gourichon Jul 23 '15 at 10:03
0

Yes it is possible, you'd do it in your msbuild script. While I can't give you an exact answer, look here at this question on SO Copy all files and folders using msbuild

Community
  • 1
  • 1
Doug Chamberlain
  • 11,192
  • 9
  • 51
  • 91