How does Copy-local work? log4net.dll is not being copied to MyProject output directory

I am wondering what copy-local=true for references exactly does. Does it copy the referenced assembly along with all of its dependencies to the output directory?

My scenario is the following: I have a custom log wrapper that utilizes log4net. I build a release assembly of MyLogWrapper.dll with log4net.dll reference set to copy-local true. Referencing MyLogWrapper.dll from MyProject with copy local set to true should result in log4net.dll being copied as well right? I am only referencing MyLogWrapper.dll and none of its dependencies in MyProject. log4net.dll is not being copied to MyProject output directory but all other dependencies of MyLogWrapper are. What could be the problem?

I have made some more experiments and it seems that if I remove the assembly (log4net.dll) from GAC it starts to get copied locally. Can anyone confirm that this is the problem?


Solution 1:

Unfortunately it appears that according to the following statement taken from the MSDN documentation the CopyLocal functionality does not work as expected for assemblies already in the GAC.

If you deploy an application that contains a reference to a custom component that is registered in the GAC, the component will not be deployed with the application, regardless of the CopyLocal setting. In previous versions of Visual Studio, you could set the CopyLocal property on a reference to ensure that the assembly was deployed. Now, you must manually add the assembly to the \Bin folder. This puts all custom code under scrutiny, reducing the risk of publishing custom code with which you are not familiar.

More information can be found at the following page which explains details about how project references work.

MSDN: Project References

Solution 2:

After asking this question on MSDN here - it seems that this behaviour is by design. "If you deploy/copy an application that contains a reference to a custom component that is registered in the GAC, the component will not be deployed/copied with the application, regardless of the Copy Local setting."

Solution 3:

There is a trick: set the reference Copy Local to false and then again to true, and Visual Studio adds the Private metadata automatically for that reference. At least VS 2010 does. I recently did this to solve an issue with our TFS Build server which for some weird reason had many Enterprise Library components installed in the GAC, so we had major issues when deploying our project from TFS Drop folder. That false/true trick saved us.

Solution 4:

You need to be a bit wary of copy local as it has caught me out in the past!

Just occasionally, for a particular .dll it will silently fail to copy it to the build folder. Usually this doesn't show up on a dev machine as the dll's are often in the GAC as well (if you have installed a dev tool / library you are using for development) and so you don't notice until it gets distrobuted / bundled into an installer and the required files are missing on a client machine.

There is not much info on this bug, but this thread demonstrates it for a particular library: here.

Having been caught by this, I think it's a good idea (generally in any case) to know exactly which assemblies are required by your project and to have a script or similar automated action which ensures all required componants are present, either when you build, or more likely when you make an installer, or collect files for distribution,