在我的Visual Studio解决方案中,我有四个项目(每个项目都针对。net 3.5)——对于我的问题,只有这两个是重要的:
这个类库引用了一个第三方DLL文件(elma . DLL)
这个web应用程序项目有一个对MyBaseProject的引用
我通过点击“添加引用…”将elmah.dll引用添加到Visual studio 2008中的MyBaseProject中。→“浏览”选项卡→选择“elmah.dll”。
Elmah Reference的属性如下:
别名-全局
本地复制- true
文化- - - - - -
错误日志模块和处理程序(ELMAH)。网
文件类型-程序集
路径- D:\webs\otherfolder\_myPath\__tools\elmah\ elmah .dll
解决-正确
运行时版本- v2.0.50727
指定版本- false
强名称- false
版本- 1.0.11211.0
在MyWebProject1中,我通过以下方式添加了对项目MyBaseProject的引用:
“添加引用……”→“项目”标签→选择“MyBaseProject”。除了以下成员之外,该引用的属性是相同的:
描述- - -
路径- D:\web \CMS\MyBaseProject\bin\Debug\MyBaseProject.dll
版本- 1.0.0.0
如果我在Visual Studio中运行构建,elmah.dll文件将被复制到我的MyWebProject1的bin目录中,以及MyBaseProject.dll!
但是,如果我清理并运行解决方案的MSBuild(通过D:\web \CMS> C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /t:ReBuild /p:Configuration=Debug MyProject.sln)
在MyWebProject1的bin目录中缺少elmah.dll -尽管构建本身没有包含警告或错误!
我已经确保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说“copy local”为真。我切换“复制本地”为假-保存-并将其设置为真-保存!)
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试图变得聪明,只把它检测到项目X需要的引用引入项目Y;它这样做是为了避免项目Y中的引用污染。问题是,由于项目X实际上不包含任何显式使用程序集B的代码(例如B.SomeFunction()), VS/MSBuild不会检测到X需要B,因此不会将B复制到项目Y的bin目录中;它只复制X和A程序集。
解决方案
您有两个选项来解决这个问题,这两个选项都将导致程序集B被复制到项目Y的bin目录:
在项目Y中添加对程序集B的引用。
向项目X中使用程序集B的文件添加伪代码。
就我个人而言,出于几个原因,我更喜欢第二种选择。
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).
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.
下面是我遇到这种情况时通常添加的“伪代码”示例。
// 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);
}