如果在解决方案中使用项目依赖关系,则MSBuild不会复制引用(DLL文件) [英] MSBuild doesn't copy references (DLL files) if using project dependencies in solution
问题描述
- MyBaseProject < - 此类库引用第三方DLL文件(elmah.dll)
- 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目录中:
- 在项目Y中添加对程序集B的引用。 >
- 将虚拟代码添加到使用程序集B的项目X中的文件中。
我个人更喜欢选项2因为几个原因。
- 如果您将来添加另一个引用项目X的项目,您将不必记住也包括对组合B的一个引用(就像你需要选择1)。
- 你可以有明确的评论,说明为什么虚拟代码需要在那里,而不是删除它。所以如果有人不小心删除了代码(比如用一个重构工具来查找未使用的代码),你可以从源代码控制中轻松地看到代码是必需的,并且还原它。如果您使用选项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:
- MyBaseProject <- this class library references a third-party DLL file (elmah.dll)
- 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:
- Add a reference to assembly B in project Y.
- Add dummy code to a file in project X that uses assembly B.
Personally I prefer option 2 for a couple reasons.
- 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.
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屋!