Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MSBuild doesn't copy references (DLL files) if using project dependencies in solution

People also ask

What is the difference between project reference and DLL reference?

If you directly add a DLL then you are locked into whatever that particular DLL was built as. The project reference allows this to be a build time decision. This is correct what you are saying. At the same time it is not causing issues when working with .

How do I add a DLL reference in Visual Studio NET core?

One of the things I did miss was a clear direction on how to reference a . NET dll directly (and of course still enjoy the benefits of intellisense), basically the same thing as doing Project > Add Reference > Browse in Visual Studio. And that's it!


I just deal with it like this. Go to the properties of your reference and do this:

Set "Copy local = false"
Save
Set "Copy local = true"
Save

and that's it.

Visual Studio 2010 doesn't initially put: <private>True</private> in the reference tag and setting "copy local" to false causes it to create the tag. Afterwards it will set it to true and false accordingly.


I'm not sure why it is different when building between Visual Studio and MsBuild, but here is what I have found when I've encountered this problem in MsBuild and Visual Studio.

Explanation

For a sample scenario let's say we have project X, assembly A, and assembly B. Assembly A references assembly B, so project X includes a reference to both A and B. Also, project X includes code that references assembly A (e.g. A.SomeFunction()). Now, you create a new project Y which references project X.

So the dependency chain looks like this: Y => X => A => B

Visual Studio / MSBuild tries to be smart and only bring references over into project Y that it detects as being required by project X; it does this to avoid reference pollution in project Y. The problem is, since project X doesn't actually contain any code that explicitly uses assembly B (e.g. B.SomeFunction()), VS/MSBuild doesn't detect that B is required by X, and thus doesn't copy it over into project Y's bin directory; it only copies the X and A assemblies.

Solution

You have two options to solve this problem, both of which will result in assembly B being copied to project Y's bin directory:

  1. Add a reference to assembly B in project Y.
  2. Add dummy code to a file in project X that uses assembly B.

Personally I prefer option 2 for a couple reasons.

  1. If you add another project in the future that references project X, you won't have to remember to also include a reference to assembly B (like you would have to do with option 1).
  2. You can have explicit comments saying why the dummy code needs to be there and not to remove it. So if somebody does delete the code by accident (say with a refactor tool that looks for unused code), you can easily see from source control that the code is required and to restore it. If you use option 1 and somebody uses a refactor tool to clean up unused references, you don't have any comments; you will just see that a reference was removed from the .csproj file.

Here is a sample of the "dummy code" that I typically add when I encounter this situation.

    // DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
    private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
    {
        // Assembly A is used by this file, and that assembly depends on assembly B,
        // but this project does not have any code that explicitly references assembly B. Therefore, when another project references
        // this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
        // assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
        // gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
        var dummyType = typeof(B.SomeClass);
        Console.WriteLine(dummyType.FullName);
    }

If you are not using the assembly directly in code then Visual Studio whilst trying to be helpful detects that it is not used and doesn't include it in the output. I'm not sure why you are seeing different behaviour between Visual Studio and MSBuild. You could try setting the build output to diagnostic for both and compare the results see where it diverges.

As for your elmah.dll reference if you are not referencing it directly in code you could add it as an item to your project and set the Build Action to Content and the Copy to Output Directory to Always.


Take a look at:

This MSBuild forum thread I started

You will find my temporary solution / workaround there!

(MyBaseProject needs some code that is referencing some classes (whatever) from the elmah.dll for elmah.dll being copied to MyWebProject1's bin!)


I had the same problem.

Check if the framework version of your project is the same of the framework version of the dll that you put on reference.

In my case, my client was compiled using "Framework 4 Client" and the DLL was in "Framework 4".


The issue I was facing was I have a project that is dependent on a library project. In order to build I was following these steps:

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package

That of course meant I was missing my library's dll files in bin and most importantly in the package zip file. I found this works perfectly:

msbuild.exe myproject.vbproj /T:Rebuild;Package

I have no idea why this work or why it didn't in the first place. But hope that helps.