views:

2430

answers:

3

Let's say we have a solution with the following structure:

  • Project.DAL - Data access layer, depends on a lower-level library, e.g. Oracle.DataAccess w/copy local = true
  • Project.BLL - Business logic layer, references Project.DAL as project
  • Project.UI - UI layer, compiles to executable, references Project.BLL, default project

When Project.UI is compiled, VS is smart enough to copy Project.DAL.dll to the output directory, but it's not smart enough to figure out that I wanted Oracle.DataAccess to be copied to the output directory as well for distribution to clients.

Can anyone explain why this is so? Is it because it sees Oracle.DataAccess in the GAC and assumes that clients will have it in the GAC as well?

It's not that big of a deal, but it's kinda annoying that every time I add a new assembly reference, I have to remember to set it to copy local and add an item to copy it in my build script as well.

+4  A: 

Yes, Visual Studio will copy a DLL to the output path in any of the two conditions below:

  1. The DLL is referenced explicitly with CopyLocal = true
  2. The DLL is referenced without CopyLocal or implicitly through some other referenced DLL and is not in the GAC

The reason why it will not copy-local when the file is in GAC, is that when resolving assembly names the GAC has highest priority, i.e. even if you have a (different) local copy, the version from the GAC will be used.

I suggest you set up a library directory where you put all external assemblies that are referenced. Then you set up an automatic MSBuild script on a computer (or VM) that does not have the Oracle-file gac'ed (nor Visual Studio installed for that sake). That way, the file will be copied to the build, and you will have more control over what is done than when using VS.

Magnus Akselvoll
+2  A: 

One more thing.

When you don't use the referenced DLL in your code at all, it will ignore the CopyLocal and won't copy it to your output directory.

Jonathan
A: 

I had a strange situation where even though the assembly was a project reference and was referenced with "Copy Local" showing up as "True" in the reference properties window, the DLL was not being copied to the output directory. I had an earlier version of the DLL in the GAC but I didn't see why this should prevent the DLL being copied.

I found that by unloading the project and manually editing the project reference XML as follows:

<ProjectReference Include="..\SomeProject.csproj">
  <Project>{11111111-1111-1111-1111-111111111111}</Project>
  <Name>Some Project Name</Name>
  <Private>True</Private>
</ProjectReference>

The DLL was copied to the ouput directory as expected. I found that just setting Copy Local to True in the properties window meant the <Private> element was completely missing, but in the case of it being set to false it was present with a value of "False".

Shaun