如果在解决scheme中使用项目依赖关系,MSBuild不会复制引用(DLL文件)
我有我的Visual Studio解决scheme中的四个项目(每个人都针对.NET 3.5) – 对于我的问题,只有这两个是重要的:
- MyBaseProject < – 这个类库引用第三方DLL文件(elmah.dll)
- 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目录中:
- 在项目Y中添加对组件B的引用。
- 将虚拟代码添加到使用程序集B的项目X中的文件
就我个人而言,我更喜欢选项2。
- 如果在将来添加另一个引用项目X的项目,则不必记住还要包含对程序集B的引用(就像你必须要做的选项1一样)。
- 你可以有明确的评论,说明为什么虚拟代码需要在那里,而不是删除它。 所以,如果有人不小心删除了代码(比如用重构工具查找未使用的代码),那么可以从源代码控制中轻松地看到代码是必需的,并且还原它。 如果使用选项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”。 这也是你已经在你的网站上指定了一个“硬编码”来使用这个实现。