小编典典

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

all

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

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

我在 Visual Studio 2008 中添加了对 MyBaseProject 的 elmah.dll 引用, 方法
是单击“添加引用…”-“浏览”选项卡-选择“elmah.dll”。

Elmah 参考的属性如下:

  • 别名 - 全局
  • 复制本地 - 真
  • 文化 -
  • 说明 - 用于 ASP.NET 的错误日志记录模块和处理程序 (ELMAH)
  • 文件类型 - 装配
  • 路径 - D:\webs\otherfolder\_myPath\__tools\elmah\Elmah.dll
  • 已解决 - 真
  • 运行时版本 - v2.0.50727
  • 指定版本 - 错误
  • 强名称 - 错误
  • 版本 - 1.0.11211.0

MyWebProject1 中 ,我通过以下方式添加了对 Project MyBaseProject
的引用:“添加引用…”——“项目”选项卡——选择“MyBaseProject”。除了以下成员之外,此引用的属性相同:

  • 描述 -
  • 路径 - D:\webs\CMS\MyBaseProject\bin\Debug\MyBaseProject.dll
  • 版本 - 1.0.0.0

如果我在 Visual Studio 中运行构建,elmah.dll 文件将与 MyBaseProject.dll 一起复制到
MyWebProject1 的 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 - 尽管构建本身不包含警告或错误!

我已经确保 MyBaseProject 的 .csproj 包含值为“true”的 私有 元素(这应该是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>

(默认情况下,私有标签没有出现在 .csproj 的 xml 中,尽管 Visual Studio 说“复制本地”为真。我将“复制本地”切换为假 - 已保存
- 并再次将其设置回真 - 保存!)

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

我不想在每个项目的 postbuild 命令中添加 postbuild 复制操作!(想象一下我会有很多项目依赖于 MyBaseProject!)


阅读 119

收藏
2022-04-25

共1个答案

小编典典

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

解释

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

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

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

解决方案

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

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

出于几个原因,我个人更喜欢选项 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);
    }
2022-04-25