292

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

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

通过单击“添加引用...”→“浏览”选项卡→选择“elmah.dll”,我在 Visual Studio 2008 中添加了对MyBaseProject的 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!)

4

20 回答 20

171

我只是这样处理它。转到参考的属性并执行以下操作:

Set "Copy local = false"
Save
Set "Copy local = true"
Save

就是这样。

Visual Studio 2010 最初并未将: <private>True</private> 放入引用标记中并将“本地复制”设置为 false 会导致它创建标记。之后,它将相应地设置为 true 和 false。

于 2011-10-21T23:54:33.953 回答
167

我不确定为什么在 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);
    }
于 2014-01-10T22:30:17.493 回答
39

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

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

于 2009-07-16T15:05:44.467 回答
16

看一眼:

我开始的这个 MSBuild 论坛主题

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

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

于 2009-07-16T10:32:53.460 回答
9

我有同样的问题。

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

就我而言,我的客户端是使用“Framework 4 Client”编译的,DLL 位于“Framework 4”中。

于 2012-01-23T13:40:26.110 回答
8

我面临的问题是我有一个依赖于库项目的项目。为了构建,我遵循以下步骤:

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package

这当然意味着我在 bin 中丢失了我的库的 dll 文件,最重要的是在包 zip 文件中。我发现这非常有效:

msbuild.exe myproject.vbproj /T:Rebuild;Package

我不知道为什么这个工作或为什么它没有放在首位。但希望这会有所帮助。

于 2012-07-18T22:49:52.250 回答
6

正如 Alex Burtsev 在评论中提到的那样,任何仅在 XAML 资源字典中使用的东西,或者在我的情况下,任何仅在 XAML 中使用而不是在代码后面的东西,都不会被 MSBuild 视为“正在使用”。

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

于 2013-08-14T00:38:34.597 回答
6

我只是遇到了完全相同的问题,结果证明是由于同一解决方案中的 2 个项目引用了不同版本的 3rd 方库。

一旦我更正了所有参考资料,一切都会完美无缺。

于 2014-02-12T15:24:53.353 回答
5

使用 deadlydog 的方案,

Y => X => A => B ,

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

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

于 2016-12-08T20:39:56.657 回答
4

将目标框架从.NET Framework 4 Client Profile更改为.NET Framework 4为我解决了这个问题。

因此,在您的示例中:将 MyWebProject1 上的目标框架设置为.NET Framework 4

于 2013-08-02T19:20:50.427 回答
3

我遇到了同样的问题,dll 是动态加载的引用。为了解决这个问题,我在 dll 的命名空间中添加了一个“使用”。现在 dll 被复制到输出文件夹中。

于 2012-06-27T09:39:57.400 回答
3

这需要向.targets您的项目添加一个文件并将其设置为包含在项目的包含部分中。

有关程序,请参见我的答案

于 2013-10-02T12:07:24.530 回答
3

引用在构建期间未使用的程序集不是正确的做法。您应该扩充您的构建文件,以便复制其他文件。通过使用构建后事件或更新属性组。

一些例子可以在其他帖子中找到

于 2013-11-26T12:52:27.157 回答
3

出现这种情况的另一种情况是,如果您在 Visual Studio 中使用较旧的“网站”项目类型。对于该项目类型,它无法引用它自己的目录结构(当前文件夹和下)之外的 .dll。因此,在上面的答案中,假设您的目录结构如下所示:

在此处输入图像描述

其中 ProjectX 和 ProjectY 是父/子目录,ProjectX 引用 A.dll 反过来又引用 B.dll,而 B.dll 在目录结构之外,例如在根目录下的 Nuget 包(Packages)中,然后是 A. dll 将被包含,但 B.dll 不会。

于 2017-03-20T18:19:29.670 回答
2

我今天遇到了类似的问题,这肯定不是您问题的答案。但我想告诉大家,并可能提供洞察力的火花。

我有一个 ASP.NET 应用程序。构建过程设置为清理然后构建。

我有两个Jenkins CI脚本。一种用于生产,一种用于暂存。我将我的应用程序部署到登台并且一切正常。已部署到生产环境,但缺少引用的 DLL 文件。这个 DLL 文件就在项目的根目录中。不在任何 NuGet 存储库中。DLL 设置为do not copy.

两个部署之间的 CI 脚本和应用程序是相同的。在暂存环境中清理和部署之后,DLL 文件仍被替换为 ASP.NET 应用程序的部署位置 ( bin/)。生产环境并非如此。

事实证明,在一个测试分支中,我在构建过程中添加了一个步骤,将这个 DLL 文件复制到bin目录中。现在是花了一点时间才弄清楚的部分。CI 过程没有自行清理。DLL 留在工作目录中,并且意外地与 ASP.NET .zip 文件打包在一起。生产分支从未以相同的方式复制 DLL 文件,也从未意外部署过它。

TLDR;检查并确保你知道你的构建服务器在做什么。

于 2016-03-19T10:19:39.843 回答
1

确保两个项目都在同一个 .net 版本中,同时检查复制本地属性,但这应该是true默认的

于 2019-02-08T08:08:51.047 回答
1

使用 Visual Studio 2015 添加附加参数

/deployonbuild=假

到 msbuild 命令行解决了这个问题。

于 2019-11-27T16:40:22.580 回答
0

我刚刚遇到了一个非常相似的问题。使用 Visual Studio 2010 编译时,DLL 文件包含在bin文件夹中。但是在使用 MSBuild 编译时,没有包含第三方 DLL 文件。

非常令人沮丧。我解决它的方法是在我的 Web 项目中包含对包的NuGet引用,即使我没有直接在那里使用它。

于 2012-08-15T22:13:38.767 回答
0

我认为@deadlydog 的答案对当前的 Nuget 系统无效。我在 Visual Studio 2022 中使用 Y => X => A => B 重新创建了场景,我所要做的就是在终端中运行命令

msbuild -t:clean,rebuild,pack
于 2021-12-31T06:14:16.353 回答
-2

在网站项目中包含来自您的项目引用的所有引用的 DLL 文件并不总是一个好主意,尤其是当您使用依赖注入时:您的 Web 项目只想添加对接口 DLL 文件/项目的引用,而不是任何具体的实现 DLL文件。

因为如果您直接添加对实现 DLL 文件/项目的引用,则无法阻止开发人员在实现 DLL 文件/项目的具体类上调用“新”而不是通过接口。您还在您的网站中声明了使用该实现的“硬代码”。

于 2013-12-04T10:57:42.170 回答