我的Visual Studio解决方案中有四个项目(每个人都针对.NET 3.5) - 对于我的问题,这两个项目很重要:
-
MyBaseProject < - 此类库引用第三方DLL文件(elmah.dll)
-
MyWebProject1 < - 此Web应用程序项目引用了MyBaseProject
我在Visual Studio 2008中添加了对 MyBaseProject 的elmah.dll引用,方法是单击"Add reference..."→"Browse" tab→选择"elmah.dll" .
Elmah Reference的属性如下:
-
别名 - 全球
-
Copy local - true
-
文化 -
-
描述 - 错误记录ASP.NET的模块和处理程序(ELMAH)
-
文件类型 - 装配
-
路径 - D:\ webs \ otherfolder \ _myPath \ __ tools \ elmah \ Elmah.dll
-
已解决 - 正确
-
运行时版本 - v2.0.50727
-
指定版本 - false
-
强名称 - 错误
-
版本 - 1.0.11211.0
在 MyWebProject1 中,我添加了对Project MyBaseProject的引用:"Add reference..."→"Projects" tab→选择"MyBaseProject" . 除以下成员外,此引用的属性相同:
-
描述 -
-
路径 - D:\ webs \ CMS \ MyBaseProject \ bin \ Debug \ MyBaseProject.dll
-
版本 - 1.0.0.0
如果我在 Visual Studio 中运行构建,则elmah.dll文件将与MyBaseProject.dll一起复制到我的 MyWebProject1's bin 目录中!
但是,如果我清理并运行 MSBuild 解决方案(通过D:\ webs \ CMS> C:\ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe / t:ReBuild / p:Configuration = Debug MyProject.sln )MyWebProject1的bin目录中的 elmah.dll is missing - 虽然构建本身不包含警告或错误!
我已经确定MyBaseProject的.csproj包含 private 元素,其值为"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说“copy local”为true . 我将“copy local”切换为false - 保存 - 并再次将其设置为true - 保存!)
What is wrong with MSBuild? How do I get the (elmah.dll) reference copied to MyWebProject1's bin?
我不想为每个项目的postbuild命令添加postbuild复制操作! (想象一下,我有很多项目依赖于MyBaseProject!)
17 回答
将目标框架从 .NET Framework 4 Client Profile 更改为 .NET Framework 4 为我解决了这个问题 .
所以在你的例子中:将MyWebProject1上的目标框架设置为 .NET Framework 4
我遇到了同样的问题,dll是一个动态加载的引用 . 为了解决这个问题,我在dll的命名空间中添加了“using” . 现在,dll将复制到输出文件夹中 .
我刚遇到一个非常类似的问题 . 使用Visual Studio 2010进行编译时,DLL文件包含在
bin
文件夹中 . 但是在使用MSBuild进行编译时,未包含第三方DLL文件 .非常令人沮丧 . 我解决它的方法是在我的web项目中包含NuGet引用,即使我没有直接在那里使用它 .
看一眼:
This MSBuild forum thread I started
你会在那里找到我的临时解决方案/解决方法!
(MyBaseProject需要一些引用elmah.dll中某些类(无论如何)的代码,以便将elmah.dll复制到MyWebProject1的bin!)
我有同样的问题 .
检查项目的框架版本是否与您引用的dll的框架版本相同 .
就我而言,我的客户端使用“Framework 4 Client”进行编译,DLL位于“Framework 4”中 .
如果您没有直接在代码中使用程序集,那么Visual Studio在尝试提供帮助时会检测到它未被使用,并且不会将其包含在输出中 . 我不确定为什么你在Visual Studio和MSBuild之间看到不同的行为 . 您可以尝试将构建输出设置为两者的诊断,并比较结果,看看它的分歧 .
至于你的elmah.dll参考,如果你没有直接在代码中引用它,你可以将它作为一个项目添加到你的项目中,并将Build Action设置为
Content
,将Copy to Output Directory设置为Always
.在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试图变得聪明,只将引用引入它检测为项目X所需的项目Y;这样做是为了避免项目Y中的参考污染 . 问题是,由于项目X实际上不包含任何明确使用程序集B的代码(例如B.SomeFunction()),VS / MSBuild不会检测到B是必需的通过X,因此不会将其复制到项目Y的bin目录中;它只复制X和A程序集 .
解决方案
您有两个选项可以解决此问题,这两个选项都会导致程序集B被复制到项目Y的bin目录中:
在项目Y中添加对程序集B的引用 .
将伪代码添加到项目X中使用程序集的文件中B.
我个人更喜欢选项2,原因有两个 .
如果您将来添加另一个引用项目X的项目,则不必记住还包括对程序集B的引用(就像您必须使用选项1一样) .
你可以有明确的评论说明为什么虚拟代码需要在那里而不是删除它 . 因此,如果有人确实删除了代码(比如使用重构工具查找未使用的代码),您可以从源代码控制中轻松地看到代码是必需的并恢复它 . 如果您使用选项1并且某人使用重构工具来清理未使用的引用,则您没有任何注释;您将看到从.csproj文件中删除了引用 .
这是我在遇到这种情况时通常会添加的“虚拟代码”示例 .
我只是像这样处理它 . 转到引用的属性并执行以下操作:
就是这样 .
Visual Studio 2010最初不会将:
<private>True</private>
放在引用标记中,将"copy local"设置为false会导致它创建标记 . 之后它将相应地设置为true和false .我面临的问题是我有一个依赖于图书馆项目的项目 . 为了构建我遵循以下步骤:
那当然意味着我在bin中丢失了我的库的dll文件,最重要的是在包zip文件中 . 我发现这很完美:
我不知道为什么这项工作或为什么它不首先 . 但希望有所帮助 .
显示的另一种情况是,如果您在Visual Studio中使用较旧的“Web站点”项目类型 . 对于该项目类型,它无法引用其自身目录结构之外的.dll(当前文件夹和向下) . 所以在上面的答案中,假设您的目录结构如下所示:
其中ProjectX和ProjectY是父/子目录,而ProjectX引用A.dll,后者又引用B.dll,而B.dll在目录结构之外,例如在根(包)上的Nuget包中,然后是A.将包括DLL,但B.dll不会 .
引用在构建期间未使用的程序集不是正确的做法 . 您应该扩充构建文件,以便复制其他文件 . 通过使用post build事件或更新属性组 .
其他一些例子可以在其他帖子中找到
MSBuild to copy dynamically generated files as part of project dependency
VS2010 How to include files in project, to copy them to build output directory automatically during build or publish
正如Alex Burtsev在评论中提到的只在XAML资源字典中使用的任何东西,或者在我的情况下,任何仅在XAML中使用而不在代码中使用的东西,都不被MSBuild视为“正在使用” .
因此,简单地在后面的一些代码中新建一个对程序集中的类/组件的虚拟引用足以让MSBuild确信该程序集实际上正在使用中 .
这需要将
.targets
文件添加到项目中,并将其设置为包含在项目的“包含”部分中 .有关步骤,请参阅my answer here .
使用deadlydog的计划,
Y => X => A => B ,
我的问题是当我构建Y时,来自X的程序集(A和B,所有15个)都没有显示在Y的bin文件夹中 .
我通过从Y中删除引用X来解决它,保存,构建,然后重新添加X引用(项目引用),并保存,构建,并且A和B开始显示在Y的bin文件夹中 .
我今天遇到了类似的问题,这肯定不是你问题的答案 . 但我想告诉大家,并可能提供一个洞察力的火花 .
我有一个ASP.NET应用程序 . 构建过程设置为clean,然后构建 .
我有两个Jenkins CI脚本 . 一个用于 生产环境 ,一个用于分期 . 我将我的应用程序部署到暂存,一切正常 . 部署到 生产环境 并丢失了引用的DLL文件 . 这个DLL文件就在项目的根目录中 . 不在任何NuGet存储库中 . DLL设置为
do not copy
.CI脚本和应用程序在两个部署之间是相同的 . 仍然在暂存环境中清理和部署之后,DLL文件在ASP.NET应用程序的部署位置(
bin/
)中被替换 . 生产环境 环境不是这种情况 .事实证明,在测试分支中,我已经在构建过程中添加了一个步骤,将此DLL文件复制到
bin
目录 . 现在需要花一点时间来弄清楚的部分 . CI过程本身并没有清理 . DLL留在工作目录中,并且意外地与ASP.NET .zip文件打包在一起 . 生产环境 分支从来没有以相同的方式复制DLL文件,从来没有不小心部署了这个 .TLDR;检查并确保您知道构建服务器正在执行的操作 .
包括来自您项目参考的所有引用的DLL文件在网站项目中并不总是一个好主意,特别是当您使用dependency injection时:您的Web项目只是想添加对接口DLL文件/项目的引用,而不是任何具体的实现DLL文件 .
因为如果直接向实现DLL文件/项目添加引用,则无法阻止开发人员在实现DLL文件/项目的具体类上而不是通过接口调用“new” . 您也在网站上声明了使用该实施的“硬编码” .
我只是遇到了完全相同的问题,结果是由于同一解决方案中的2个项目引用了第三方库的不同版本 .
一旦我纠正了所有参考文献,一切都很完美 .