如果在解决方案中使用项目依赖关系,则MSBuild不会复制引用(DLL文件) [英] MSBuild doesn't copy references (DLL files) if using project dependencies in solution

查看:214
本文介绍了如果在解决方案中使用项目依赖关系,则MSBuild不会复制引用(DLL文件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Visual Studio解决方案中有四个项目(每个人都是.NET 3.5) - 对于我的问题,只有这两个项目很重要:


  1. MyBaseProject < - 此类库引用第三方DLL文件(elmah.dll)

  2. MyWebProject1 < - 这Web应用程序项目引用了MyBaseProject

我在Visual Studio中将elmah.dll引用添加到 MyBaseProject 2008年,点击添加引用...→浏览选项卡→选择elmah.dll。



Elmah参考的属性如下: / p>


  • 别名 - 全球

  • 复制本地 - 真实

  • 文化 -

  • 描述 - ASP.NET的错误日志模块和处理程序(ELMAH)

  • 文件类型 - / li>
  • 路径-D:\webs\otherfolder\_myPath\__tools\elmah\Elmah.dll

  • Res olved - True

  • 运行时版本 - v2.0.50727

  • 指定版本 - false

  • 强名称 - false

  • 版本 - 1.0.11211.0



MyWebProject1 参考Project MyBaseProject by:
添加引用...→项目选项卡→选择MyBaseProject。此参考的属性与以下成员相同:




  • 描述 -

  • 路径 - D:\webs\CMS\MyBaseProject\bin\Debug\MyBaseProject.dll

  • 版本 - 1.0.0.0



如果我在 Visual Studio 中运行构建,elmah.dll文件将与MyBaseProject一起复制到MyWebProject1的bin 目录中。 dll!



但是,如果我清理并运行 MSBuild (通过D:\webs\CMS> C:\WINDOWS \Microsoft.NET\Framework\v3.5\MSBuild.exe / t:ReBuild / p:Configuration = Debug MyProject.sln)
elmah.dll缺少 MyWebProject1的bin目录 - 虽然构建本身不包含警告或错误!



我已经确定MyBaseProject的.csproj包含 private 元素值为true(应该是一个别名)在Visual Studio中为复制本地):

 <引用包含=Elmah,版本= 1.0.11211.0,Culture = neutral,processorArchitecture = MSIL> 
< SpecificVersion> False< / SpecificVersion>
< HintPath> .. \mypath\__tools\elmah\Elmah.dll< / HintPath>
**< Private> true< / Private> **
< / Reference>

(默认情况下,私有标签没有出现在.csproj的xml中,尽管Visual Studio说复制本地真实的,我将本地复制到虚假 - 保存 - 并将其重新设置为true - 保存!)



MSBuild有什么问题?我如何将(elmah.dll)引用复制到MyWebProject1的bin?



我不想在每个项目的postbuild命令中添加一个postbuild复制操作! (想象一下,我会有很多项目依赖于MyBaseProject!)

解决方案

我不知道为什么在Visual Studio和MsBuild,但是当我在MsBuild和Visual Studio中遇到这个问题时,这里是我发现的。



说明



对于示例场景,我们假设我们有项目X,程序集A和程序集B.程序集A引用程序集B,因此项目X包括对A和B的引用。另外,项目X还包括引用程序集A(例如A.SomeFunction())。现在,您创建一个引用项目X的新项目Y.



因此,依赖关系链如下所示: Y => X => A => B



Visual Studio / MSBuild尝试聪明,只会将项目Y中的引用引用到项目X所要求的项目Y中;这样做是为了避免项目Y中的引用污染。问题是,由于项目X实际上并不包含明确使用汇编B(例如B.SomeFunction())的任何代码,所以VS / MSBuild不会检测到需要B由X,因此不会将其复制到项目Y的bin目录中;它只复制X和A程序集。



解决方案



您有两个选项可以解决这个问题,这将导致程序集B被复制到项目Y的bin目录中:


  1. 在项目Y中添加对程序集B的引用。 >
  2. 将虚拟代码添加到使用程序集B的项目X中的文件中。

我个人更喜欢选项2因为几个原因。


  1. 如果您将来添加另一个引用项目X的项目,您将不必记住也包括对组合B的一个引用(就像你需要选择1)。

  2. 你可以有明确的评论,说明为什么虚拟代码需要在那里,而不是删除它。所以如果有人不小心删除了代码(比如用一个重构工具来查找未使用的代码),你可以从源代码控制中轻松地看到代码是必需的,并且还原它。如果您使用选项1,有人使用重构工具清理未使用的引用,则您没有任何注释;您将看到从.csproj文件中删除了一个引用。

这里是一个虚拟代码的示例,通常在遇到这种情况时添加。

  //不要删除此代码,除非我们不需要组装一个! 
private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
{
//程序集A由此文件使用,该程序集取决于程序集B,
//但是该项目没有任何代码因此,当另一个项目引用
//这个项目时,该项目的程序集和程序集A被复制到项目的bin目录,而不是
// assembly B.所以按顺序要复制所需的程序集B,我们在这里添加一些引用程序集B的虚拟代码(从未
//被调用)这将标志VS / MSBuild复制所需的程序集B。
var dummyType = typeof(B.SomeClass);
Console.WriteLine(dummyType.FullName);
}


I have four projects in my Visual Studio solution (everyone targeting .NET 3.5) - for my problem only these two are important:

  1. MyBaseProject <- this class library references a third-party DLL file (elmah.dll)
  2. MyWebProject1 <- this web application project has a reference to MyBaseProject

I added the elmah.dll reference to MyBaseProject in Visual studio 2008 by clicking "Add reference..." → "Browse" tab → selecting the "elmah.dll".

The Properties of the Elmah Reference are as follows:

  • Aliases - global
  • Copy local - true
  • Culture -
  • Description - Error Logging Modules and Handlers (ELMAH) for ASP.NET
  • File Type - Assembly
  • Path - D:\webs\otherfolder\_myPath\__tools\elmah\Elmah.dll
  • Resolved - True
  • Runtime version - v2.0.50727
  • Specified version - false
  • Strong Name - false
  • Version - 1.0.11211.0

In MyWebProject1 I added the reference to Project MyBaseProject by: "Add reference..." → "Projects" tab → selecting the "MyBaseProject". The Properties of this reference are the same except the following members:

  • Description -
  • Path - D:\webs\CMS\MyBaseProject\bin\Debug\MyBaseProject.dll
  • Version - 1.0.0.0

If I run the build in Visual Studio the elmah.dll file is copied to my MyWebProject1's bin directory, along with MyBaseProject.dll!

However if I clean and run MSBuild for the solution (via D:\webs\CMS> C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /t:ReBuild /p:Configuration=Debug MyProject.sln) the elmah.dll is missing in MyWebProject1's bin directory - although the build itself contains no warning or errors!

I already made sure that the .csproj of MyBaseProject contains the private element with the value "true" (that should be an alias for "copy local" in Visual Studio):

<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
    **<Private>true</Private>**
</Reference>

(The private tag didn't appear in the .csproj's xml by default, although Visual Studio said "copy local" true. I switched "copy local" to false - saved - and set it back to true again - save!)

What is wrong with MSBuild? How do I get the (elmah.dll) reference copied to MyWebProject1's bin?

I do NOT want to add a postbuild copy action to every project's postbuild command! (Imagine I would have many projects depend on MyBaseProject!)

解决方案

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);
    }

这篇关于如果在解决方案中使用项目依赖关系,则MSBuild不会复制引用(DLL文件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆