如果在解决scheme中使用项目依赖关系,MSBuild不会复制引用(DLL文件)

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

  1. MyBaseProject < – 这个类库引用第三方DLL文件(elmah.dll)
  2. MyWebProject1 < – 此Web应用程序项目具有对MyBaseProject的引用

我通过点击“添加引用…”→“浏览”选项卡→select“elmah.dll”,在Visual Studio 2008中添加了elmah.dll引用到MyBaseProject

Elmah参考的属性如下:

  • 别名 – 全球
  • 复制本地 – 真实
  • 文化 –
  • 说明 – 错误logging模块和处理程序(ELMAH)for ASP.NET
  • 文件types – 组装
  • path – D:\ webs \ otherfolder \ _myPath \ __ tools \ elmah \ Elmah.dll
  • 解决 – 真的
  • 运行时版本 – v2.0.50727
  • 指定的版本 – 错误
  • 强名 – 错误
  • 版本 – 1.0.11211.0

MyWebProject1中,我添加了对Project MyBaseProject的引用:“Add reference …”→“Projects”选项卡→select“MyBaseProject”。 除下列成员外,此参考的属性相同:

  • 说明 –
  • path – D:\ webs \ CMS \ MyBaseProject \ bin \ Debug \ MyBaseProject.dll
  • 版本 – 1.0.0.0

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

但是如果我清理并运行解决scheme的MSBuild (通过D:\ webs \ CMS> C:\ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe / t:ReBuild / p:Configuration = Debug MyProject.sln )在MyWebProject1的bin目录中缺less elmah.dll – 尽pipe构build本身不包含任何警告或错误!

我已经确保MyBaseProject的.csproj包含值为“true”的私有元素(这应该是Visual Studio中“ copy local ”的别名):

<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> 

(私有标签没有出现在.csproj的xml默认情况下,虽然Visual Studio说“复制本地”的真实。我把“复制本地”为假 – 保存 – 并将其重新设置为真 – 保存!

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

我不想为每个项目的构build命令添加一个构build后的复制操作! (想象一下,我将有许多项目依赖于MyBaseProject!)

我不确定在Visual Studio和MsBuild之间构build时为什么会有所不同,但是这里是我在MsBuild和Visual Studio中遇到这个问题时发现的。

说明

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

所以依赖链看起来像这样: Y => X => A => B

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

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

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

就我个人而言,我更喜欢选项2。

  1. 如果在将来添加另一个引用项目X的项目,则不必记住还要包含对程序集B的引用(就像你必须要做的选项1一样)。
  2. 你可以有明确的评论,说明为什么虚拟代码需要在那里,而不是删除它。 所以,如果有人不小心删除了代码(比如用重构工具查找未使用的代码),那么可以从源代码控制中轻松地看到代码是必需的,并且还原它。 如果使用选项1,并且有人使用重构工具来清理未使用的引用,则不需要任何注释。 你只会看到从.csproj文件中删除了一个引用。

下面是我遇到这种情况时通常添加的“虚拟代码”示例。

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

我只是这样处理。 转到您的参考的属性,并执行此操作:

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

就是这样。

Visual Studio 2010最初不会在参考标记中放置<private>True</private> ,并将“copy local”设置为false,导致它创build标记。 之后它将相应地设置为真和假。

如果您没有直接在代码中使用程序集,Visual Studio在试图帮助时会检测到它没有被使用,并且不会将其包含在输出中。 我不知道你为什么看到Visual Studio和MSBuild之间的不同行为。 您可以尝试将生成输出设置为诊断,并比较结果,看看它在哪里分歧。

至于你的elmah.dll参考,如果你没有直接在代码中引用它,你可以把它作为一个项目添加到你的项目,并将生成操作设置为Content和复制到输出目录为Always

看一眼:

这MSBuild论坛线程我开始了

你会在那里find我的临时解决scheme/解决方法!

(MyBaseProject需要一些代码,引用Elmah.dll中的一些类(无论),将elmah.dll拷贝到MyWebProject1的bin中!)

我有同样的问题。

检查您的项目的框架版本是否与您引用的dll的框架版本相同。

在我的情况下,我的客户端使用“Framework 4 Client”进行编译,DLL在“Framework 4”中。

我面临的问题是我有一个依赖于图书馆项目的项目。 为了build立我是以下步骤:

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

这当然意味着我在bin中丢失了我的库的dll文件,最重要的是在包zip文件中。 我发现这完美的作品:

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

我不知道为什么这项工作或为什么不摆在首位。 但希望有所帮助。

正如Alex Burtsev在评论中提到的任何仅用于XAML资源字典的东西,或者在我的情况下,任何仅用于XAML而不用于代码的东西都不被视为“由MSBuild使用”。

所以简单地在后面的代码中新build一个对类/组件的虚引用足以说服MSBuild程序集实际上正在使用。

将目标框架从.NET Framework 4 Client Profile更改为.NET Framework 4为我解决了这个问题。

所以在你的例子中:将MyWebProject1上的目标框架设置为.NET Framework 4

我刚刚有完全相同的问题,原来是由于在同一个解决scheme中的2个项目引用不同版本的第三方库。

一旦我纠正所有的参考一切工作完美。

我有同样的问题,而DLL是一个dynamic加载的参考。 为了解决这个问题,我在dll的命名空间中添加了一个“using”。 现在该DLL被复制到输出文件夹中。

这需要添加一个.targets文件到您的项目中,并将其设置为包含在项目的包含部分。

查看我的答案在这里的程序。

引用在构build期间不使用的程序集不是正确的做法。 您应该扩充您的构build文件,以便它将复制其他文件。 通过使用后构build事件或通过更新属性组。

一些例子可以在其他post中find

  • MSBuild复制dynamic生成的文件作为项目依赖项的一部分
  • VS2010如何在项目中包含文件,将其复制到构build或发布期间自动生成输出目录

用deadlydog的scheme,

Y => X => A => B

我的问题是当我build立Y时,来自X的程序集(A和B,它们全部15个)没有出现在Y的bin文件夹中。

我解决了从Y中删除引用X,保存,生成,然后重新添加X引用(项目引用),并保存,build立,A和B开始显示在Y的bin文件夹。

另一种情况是,如果在Visual Studio中使用较旧的“Web Site”项目types。 对于该项目types,无法引用位于其自身目录结构(当前文件夹和下)之外的.dll文件。 所以在上面的答案中,假设你的目录结构如下所示:

在这里输入图像描述

在ProjectX和ProjectY是父/子目录的情况下,ProjectX引用A.dll,后者又引用B.dll和B.dll,而不在目录结构之外,例如在根(Packages)上的Nuget包中,然后是A. DLL将被列入,但B.dll不会。

我遇到了一个非常类似的问题。 在使用Visual Studio 2010编译时,DLL文件包含在bin文件夹中。 但是,使用MSBuild编译时,不包含第三方DLL文件。

非常令人沮丧。 我解决这个问题的方法是在我的Web项目中包含NuGet引用,尽pipe我并没有直接使用它。

今天我有类似的问题,这当然不是你的问题的答案。 但是我想告诉大家,并且可能提供一个洞察力的火花。

我有一个ASP.NET应用程序。 构build过程被设置为清理然后构build。

我有两个Jenkins CI脚本。 一个用于生产,一个用于分期。 我部署我的应用程序分段,一切正常。 部署到生产并丢失了被引用的DLL文件。 这个DLL文件只是在项目的根。 不在任何NuGet存储库中。 该DLL被设置为do not copy

CI脚本和应用程序在两个部署之间是相同的。 仍然在临时环境中进行清理和部署之后,DLL文件在ASP.NET应用程序的部署位置( bin/ )中被replace。 生产环境并非如此。

事实certificate,在一个testing分支中,我已经添加了一个步骤到生成过程,将该DLL文件复制到bin目录。 现在花了一些时间来弄清楚的部分。 CIstream程并没有自行清理。 该DLL被留在工作目录中,并被意外打包在ASP.NET .zip文件中。 生产分支从来没有以相同的方式复制DLL文件,并从来没有意外地部署这个。

TLDR; 检查并确保你知道你的构build服务器在做什么。

在Website项目中包含所有从项目引用引用的DLL文件并不总是一个好主意,尤其是当您使用dependency injection时 :您的Web项目只是想添加对接口DLL文件/项目的引用,而不是任何具体的实现DLL文件。

因为如果直接向实现DLL文件/项目添加引用,则无法阻止开发人员通过接口调用实现DLL文件/项目的具体类上的“新build”。 这也是你已经在你的网站上指定了一个“硬编码”来使用这个实现。