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

toe*_*ens 271 msbuild dependencies reference project visual-studio

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

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

我加入了elmah.dll参考MyBaseProject通过点击在Visual Studio 2008中的"添加引用..."→"浏览"选项卡→选择"elmah.dll".

Elmah Reference的属性如下:

  • 别名 - 全球
  • 复制本地 - 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"选项卡→选择"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中" 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>
Run Code Online (Sandbox Code Playgroud)

(默认情况下,私有标签没有出现在.csproj的xml中,虽然Visual Studio说"copy local"为true.我将"copy local"切换为false - 保存 - 并再次将其设置为true - 保存!)

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

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

and*_*rew 169

我只是像这样处理它.转到引用的属性并执行以下操作:

Set "Copy local = false"
Save
Set "Copy local = true"
Save
Run Code Online (Sandbox Code Playgroud)

就是这样.

Visual Studio 2010最初没有放入: <private>True</private> 在引用标记中并将"copy local"设置为false会导致它创建标记.之后它将相应地设置为true和false.

  • 使用MSBuild 4/VS2012不适用于我.也就是说,我能够更新引用"<Private> true </ Private>",但它似乎对MSBuild没有影响.最后,我刚刚添加了对下层项目的NuGet引用. (22认同)
  • 这是天赐之物.这次真是万分感谢! (10认同)
  • 看起来VS2015的行为仍然相同:将"Copy Local"设置为"False",然后在引用的.dll上设置回"True",有效. (6认同)
  • 这相当于"你试过把它关掉再打开吗?",它有效! (4认同)
  • 不适合我.它仍然不会将System.Net.Http.Formatting复制到bin文件夹. (2认同)

dea*_*dog 147

我不确定为什么在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目录中:

  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);
    }
Run Code Online (Sandbox Code Playgroud)

  • 除非您在Visual Studio中选中了"优化代码"设置,否则上面显示的解决方案#2将起作用.在这种情况下,它仍将排除dll.我添加了一行来覆盖它的"优化".`Console.WriteLine(dummyType.FullName);` (13认同)
  • 你能解释为什么它与VS合作而没有添加"虚拟代码"而不是msbuild吗? (4认同)
  • 这里没有讨论的是,在web项目的/ bin中复制构建产品和将例程复制到目标输出目录(例如/ bin/x86/Debug)之间存在差异.前者由引用的项目在构建时完成,后者由依赖的Web项目完成.检查Microsoft.Common.targets有助于理解这一点.复制到web/bin根本不依赖于复制本地行为 - 将副本上的本地影响复制到输出目标dir,该目标dir不是通过Debug运行的Cassini引用的结构的一部分. (3认同)
  • 解决方案2在Visual Studio 2017中对我不起作用.我首先想到的是,在我的程序集X中,我只使用了来自B的`enum`而我假设枚举被内联.我添加了代码直接使用B中的类型,但没有帮助.一直以来我的X在A中使用类型B中的子类类型,因此我无法理解编译器如何认为X不需要B并且可以忽略.这是疯子. (3认同)
  • 除了比调用函数更具侵入性之外,您还可以将程序集中包含的类的类型分配给虚拟变量.`输入dummyType = typeof(AssemblyA.AnyClass);` (2认同)

Joh*_*ter 38

如果您没有直接在代码中使用程序集,那么Visual Studio在尝试帮助时会检测到它未被使用,并且不会将其包含在输出中.我不确定为什么你会在Visual Studio和MSBuild之间看到不同的行为.您可以尝试将构建输出设置为两者的诊断,并比较结果以查看它的分歧.

至于你的elmah.dll参考,如果你没有直接在代码中引用它,你可以将它作为一个项目添加到你的项目中,并将Build Action设置为Content和Copy to Output Directory Always.

  • 实际上,它忽略了未使用的程序集,但有一点需要注意,因为VS 2010中使用XAML资源字典中的程序集不被VS视为使用,因此它不会复制它. (4认同)
  • 如果您没有在代码中使用Elmah,则将您的副本+1给输出目录注释,将其复制为内容是有意义的. (3认同)
  • https://connect.microsoft.com/VisualStudio/feedback/details/693740/msbuild-doesnt-include-assemblies-as-dependencies-from-referenced-projects-if-they-are-used-in-xaml-resource-字典 (3认同)

toe*_*ens 14

看一眼:

这个MSBuild论坛帖子我开始了

你会在那里找到我的临时解决方案/解决方法!

(MyBaseProject需要一些引用elmah.dll中某些类(无论如何)的代码,以便将elmah.dll复制到MyWebProject1的bin!)

  • 请参阅以下安德鲁的反应意见,以获得一个不那么糟糕的解决方案(没有冒犯!) (2认同)

小智 8

我有同样的问题.

检查项目的框架版本是否与您引用的dll的框架版本相同.

在我的例子中,我的客户端使用"Framework 4 Client"编译,DLL在"Framework 4"中.


van*_*rra 6

我面临的问题是我有一个依赖于图书馆项目的项目.为了构建我遵循以下步骤:

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package
Run Code Online (Sandbox Code Playgroud)

那当然意味着我在bin中丢失了我的库的dll文件,最重要的是在包zip文件中.我发现这很完美:

msbuild.exe myproject.vbproj /T:Rebuild;Package
Run Code Online (Sandbox Code Playgroud)

我不知道为什么这项工作或为什么它一开始就没有.但希望有所帮助.


Sco*_*ott 6

正如 Alex Burtsev 在评论中提到的,任何只在 XAML 资源字典中使用的东西,或者在我的例子中,只在 XAML 中使用而不是在代码背后的任何东西,都不会被 MSBuild 视为“正在使用”。

因此,只需在后面的某些代码中新建对程序集中的类/组件的虚拟引用,就足以让 MSBuild 相信该程序集已在实际使用中。


小智 5

我只是遇到了完全相同的问题,而事实是,同一解决方案中的2个项目引用了第3方库的不同版本这一事实引起了。

一旦我纠正了所有参考文献,一切都将正常运行。


小智 5

使用deadlydog的方案,

Y => X => A => B ,

我的问题是当我构建 Y 时,来自 X 的程序集(A 和 B,全部 15 个)没有出现在 Y 的 bin 文件夹中。

我通过从 Y 中删除引用 X,保存,构建,然后重新添加 X 引用(项目引用),并保存、构建和 A 和 B 开始显示在 Y 的 bin 文件夹中来解决它。