首页 文章

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

提问于
浏览
254

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

  • MyBaseProject < - 此类库引用第三方DLL文件(elmah.dll)

  • MyWebProject1 < - 此Web应用程序项目引用了MyBaseProject

我在Visual Studio 2008中添加了对 MyBaseProject 的elmah.dll引用,方法是单击"Add reference..."→"Browse" tab→选择"elmah.dll" .

Elmah Reference的属性如下:

  • 别名 - 全球

  • Copy local - 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" tab→选择"MyBaseProject" . 除以下成员外,此引用的属性相同:

  • 描述 -

  • 路径 - D:\ webs \ CMS \ MyBaseProject \ bin \ Debug \ MyBaseProject.dll

  • 版本 - 1.0.0.0

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

我已经确定MyBaseProject的.csproj包含 private 元素,其值为"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”为true . 我将“copy local”切换为false - 保存 - 并再次将其设置为true - 保存!)

What is wrong with MSBuild? How do I get the (elmah.dll) reference copied to MyWebProject1's bin?

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

17 回答

  • 163

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

    所以在你的例子中:将MyWebProject1上的目标框架设置为 .NET Framework 4

  • 2

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

  • 8

    我刚遇到一个非常类似的问题 . 使用Visual Studio 2010进行编译时,DLL文件包含在 bin 文件夹中 . 但是在使用MSBuild进行编译时,未包含第三方DLL文件 .

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

  • 3

    看一眼:

    This MSBuild forum thread I started

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

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

  • 3

    我有同样的问题 .

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

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

  • 6

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

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

  • 2

    在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目录中:

    • 在项目Y中添加对程序集B的引用 .

    • 将伪代码添加到项目X中使用程序集的文件中B.

    我个人更喜欢选项2,原因有两个 .

    • 如果您将来添加另一个引用项目X的项目,则不必记住还包括对程序集B的引用(就像您必须使用选项1一样) .

    • 你可以有明确的评论说明为什么虚拟代码需要在那里而不是删除它 . 因此,如果有人确实删除了代码(比如使用重构工具查找未使用的代码),您可以从源代码控制中轻松地看到代码是必需的并恢复它 . 如果您使用选项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);
        }
    
  • 2

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

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

    就是这样 .

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

  • 2

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

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

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

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

    我不知道为什么这项工作或为什么它不首先 . 但希望有所帮助 .

  • 137

    显示的另一种情况是,如果您在Visual Studio中使用较旧的“Web站点”项目类型 . 对于该项目类型,它无法引用其自身目录结构之外的.dll(当前文件夹和向下) . 所以在上面的答案中,假设您的目录结构如下所示:

    enter image description here

    其中ProjectX和ProjectY是父/子目录,而ProjectX引用A.dll,后者又引用B.dll,而B.dll在目录结构之外,例如在根(包)上的Nuget包中,然后是A.将包括DLL,但B.dll不会 .

  • 38

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

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

  • 14

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

    因此,简单地在后面的一些代码中新建一个对程序集中的类/组件的虚拟引用足以让MSBuild确信该程序集实际上正在使用中 .

  • 4

    这需要将 .targets 文件添加到项目中,并将其设置为包含在项目的“包含”部分中 .

    有关步骤,请参阅my answer here .

  • 0

    使用deadlydog的计划,

    Y => X => A => B

    我的问题是当我构建Y时,来自X的程序集(A和B,所有15个)都没有显示在Y的bin文件夹中 .

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

  • 0

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

    我有一个ASP.NET应用程序 . 构建过程设置为clean,然后构建 .

    我有两个Jenkins CI脚本 . 一个用于 生产环境 ,一个用于分期 . 我将我的应用程序部署到暂存,一切正常 . 部署到 生产环境 并丢失了引用的DLL文件 . 这个DLL文件就在项目的根目录中 . 不在任何NuGet存储库中 . DLL设置为 do not copy .

    CI脚本和应用程序在两个部署之间是相同的 . 仍然在暂存环境中清理和部署之后,DLL文件在ASP.NET应用程序的部署位置( bin/ )中被替换 . 生产环境 环境不是这种情况 .

    事实证明,在测试分支中,我已经在构建过程中添加了一个步骤,将此DLL文件复制到 bin 目录 . 现在需要花一点时间来弄清楚的部分 . CI过程本身并没有清理 . DLL留在工作目录中,并且意外地与ASP.NET .zip文件打包在一起 . 生产环境 分支从来没有以相同的方式复制DLL文件,从来没有不小心部署了这个 .

    TLDR;检查并确保您知道构建服务器正在执行的操作 .

  • -3

    包括来自您项目参考的所有引用的DLL文件在网站项目中并不总是一个好主意,特别是当您使用dependency injection时:您的Web项目只是想添加对接口DLL文件/项目的引用,而不是任何具体的实现DLL文件 .

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

  • 2

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

    一旦我纠正了所有参考文献,一切都很完美 .

相关问题