从属 DLL 未复制到 Visual Studio 中的生成输出文件夹

Posted

技术标签:

【中文标题】从属 DLL 未复制到 Visual Studio 中的生成输出文件夹【英文标题】:Dependent DLL is not getting copied to the build output folder in Visual Studio 【发布时间】:2013-03-26 20:32:10 【问题描述】:

我有一个视觉工作室解决方案。 我在解决方案中有很多项目。 有一个主要项目作为启动并使用其他项目。 有一个项目说“ProjectX”。它的引用被添加到主项目中。 ProjectX 引用了另一个不属于解决方案的 .NET dll(比如 abc.dll)。

现在这个 abc.dll 应该被复制到主项目的 bin/debug 文件夹,但它没有被复制到那里。为什么它没有被复制,任何已知原因?

【问题讨论】:

如果您无法解决这个问题,请将其复制到您的预构建中。 您如何在主项目中使用您的“ProjectX” - 项目的类型、目标等是什么。 我遇到了同样的问题,这个答案解决了我的问题:***.com/a/8213977/174469 Msbuild doesn't copy references (dlls) if using project dependencies in solution的可能重复 RestoreProjectStylesolution available。这个想法是为解决方案中的每个 .Net Framework 项目设置<RestoreProjectStyle>PackageReference</RestoreProjectStyle> 【参考方案1】:

我有一个类似的问题,我作为内容包含在项目中的 DLL 并设置了“始终复制”,但没有被复制到 bin 文件夹中。我通过在 app.config 中添加对 DLL 的dependentAssembly 引用解决了这个问题。

【讨论】:

【参考方案2】:

确保您使用的依赖 DLL 的目标 .NET Framework 不高于项目应用程序的目标 .NET Framework。

您可以通过选择您的项目来检查这一点,然后按 ALT+ENTER,然后从左侧选择应用程序,然后选择项目的目标框架。

假设, 依赖 DLL 目标框架 = 4.0 和 Application DLL Target Framework = 3.5 然后将其更改为 4.0

谢谢!

【讨论】:

【参考方案3】:

问题:

在构建输出不包含引用的 DLL 的 NuGet 包 DLL (Newtonsoft.json.dll) 中遇到类似问题。但是编译很顺利。

修复:

在文本编辑器中浏览您的项目并查找其中带有“私人”标签的引用。喜欢真或假。 “私人”是“复制本地”的同义词。在操作的某个地方,MSBuild 正在寻找依赖项,它在其他地方找到您的依赖项并决定不复制它。

因此,请检查每个 .csproj/.vbproj 文件并手动删除标签。重建,一切都在 Visual Studio 和 MSBuild 中工作。完成该工作后,您可以返回并将其更新到您认为需要的位置。

参考:

https://www.paraesthesia.com/archive/2008/02/13/what-to-do-if-copy-local-works-in-vs-but.aspx/

【讨论】:

【参考方案4】:

VS2019 V16.6.3

对我来说,问题是不知何故,主 .proj 文件以这样的条目结束,其 DLL 没有被复制到父项目 bin 文件夹中的项目:

<ProjectReference Include="Project B.csproj">
  <Project>blah blah</Project>
  <Name>Project B</Name>
  <Private>True</Private>
</ProjectReference>

我手动删除了&lt;Private&gt;True&lt;/Private&gt; 行,然后在每次构建主项目时将 DLL 复制到主项目 bin 文件夹中。

如果您在主项目的引用文件夹中转到问题项目的引用,单击它并查看属性有一个“复制本地”设置。私有标签等同于此设置,但出于某种原因,更改本地副本对 .proj 文件中的私有标签没有影响。

令人讨厌的是,我没有更改引用的副本本地值,不知道它是如何设置的,又浪费了一天时间来追踪 VS 的一个愚蠢问题。

感谢所有其他帮助我了解原因的答案。

HTH

【讨论】:

【参考方案5】:

TLDR; Visual Studio 2019 可能只需要重启。

我在使用基于 Microsoft.NET.Sdk 项目的项目时遇到了这种情况。

<Project Sdk="Microsoft.NET.Sdk">

具体来说:

Project1:目标.netstandard2.1 通过 Nuget 引用 Microsoft.Extensions.Logging.Console Project2:目标.netstandard2.1 通过项目引用引用 Project1 Project2Tests:目标.netcoreapp3.1 通过项目引用引用 Project2

在测试执行时,我收到错误消息,指出找不到Microsoft.Extensions.Logging.Console,并且确实不在输出目录中

我决定通过将Microsoft.Extensions.Logging.Console 添加到Project2 来解决此问题,结果发现Visual Studio 的Nuget Manager 没有列出Project1 中安装的Microsoft.Extensions.Logging.Console,尽管它存在于Project1.csproj 文件中.

简单地关闭并重新启动 Visual Studio 即可解决问题,无需添加额外的引用。也许这可以为某人节省 45 分钟的生产力损失 :-)

【讨论】:

实际上我在测试的过程中重新启动了整个 PC,但它对我有用 我在使用 SDK 项目 .NET5 时遇到了同样的问题,我尝试了这个解决方案,但不幸的是它对我不起作用,即使重新启动 PC :(【参考方案6】:

就我而言,这是最愚蠢的事情,由我不同意的 TFS/VS 的默认行为引起。

由于添加 dll 作为对主项目的引用不起作用,我决定将其添加为“现有项目”,其中 Copy Local = Always。即使那样,文件也不存在。

事实证明,即使文件存在于 VS 解决方案中并且所有内容都在本地和服务器上编译,VS/TFS 并没有实际添加文件到源代码管理。它根本不包含在“待定更改”中。我必须手动转到源代码管理资源管理器并明确单击“将项目添加到文件夹”图标。

愚蠢,因为我已经在 VS 中开发了 15 年。我以前遇到过这种情况,我只是不记得了,不知何故我错过了它,因为由于文件是常规引用,所有内容仍然编译,但是作为现有项目添加的文件没有被复制,因为它不存在源代码管理服务器。

我希望这可以节省一些时间,因为我为此损失了 2 天的生命。

【讨论】:

感激不尽……您为我节省了很多时间。这对我来说是解决方案。它还暴露了根本问题,我作为引用添加的 DLL 匹配了gitignore 模式,因此在添加为引用时它没有添加到项目中。您必须手动将文件添加到源代码管理!!!【参考方案7】:

如果您右键单击引用的程序集,您将看到一个名为 Copy Local 的属性。如果 Copy Local 设置为 true,则程序集应包含在 bin 中。 但是,Visual Studio 似乎存在问题,有时它不包含 bin 文件夹中引用的 dll……这是对我有用的解决方法:

【讨论】:

复制 Loal 被禁用,这有助于***.com/questions/15526491/…【参考方案8】:

我会将它添加到 Postbuild 事件中,以将必要的库复制到输出目录。类似 XCopy pathtolibraries 目标目录的东西

您可以在项目属性 -> 构建事件中找到它们。

【讨论】:

这对我有用,我认为这是更好的答案。虚拟参考解决方案有效,但它是一种 hack,而构建后规则是实现相同结果的一种干净方法。【参考方案9】:

将 DLL 作为现有项添加到其中一个项目中,并且应该对其进行排序

【讨论】:

【参考方案10】:

当你把它作为一个程序集属性时,它看起来很漂亮

[AttributeUsage(AttributeTargets.Assembly)]
public class ForceAssemblyReference: Attribute
        
    public ForceAssemblyReference(Type forcedType)
    
        //not sure if these two lines are required since 
        //the type is passed to constructor as parameter, 
        //thus effectively being used
        Action<Type> noop = _ =>  ;
        noop(forcedType);
    

用法如下:

[assembly: ForceAssemblyReference(typeof(AbcDll.AnyClass))]

【讨论】:

谢谢,但对我来说,这仅在我将程序集属性添加到已引用 AbcDll.AnyClass 的依赖项(项目 X)时才起作用。然后,它不会做更多的事情,它将 AbcDll 复制到依赖项的输出目录。它仍然不会将其复制到主要依赖项目的输出中。除非我还添加对 AbcDll 的引用,否则我无法将该属性添加到依赖程序集。当我这样做时,AbcDll 已经在没有属性的情况下被复制了。【参考方案11】:

这是对 nvirth 示例的细微调整

internal class DummyClass

    private static void Dummy()
    
        Noop(typeof(AbcDll.AnyClass));
    
    private static void Noop(Type _)  

【讨论】:

【参考方案12】:

代码中不需要假人 只是:

添加对可执行项目的引用

或/并确保可执行项目中的引用将"Copy Local" 设置为TRUE(这是我的“错误”)似乎这个“覆盖” em> 基础引用库项目中的设置...

【讨论】:

【参考方案13】:

除了上面常见的之外,我还有一个多项目解决方案要发布。显然有些文件针对不同的框架。

所以我的解决方案:属性>特定版本(假)

【讨论】:

【参考方案14】:

我发现如果 ProjectX 引用了 abc.dll 但没有直接使用任何在 abc.dll 中定义的类型,那么 abc.dll 将不会被复制到主输出文件夹。 (它将被复制到 ProjectX 输出文件夹中,以使其更加混乱。)

因此,如果您没有在 ProjectX 中的任何位置显式使用 abc.dll 中的任何类型,那么请在 ProjectX 的某个文件中的某个位置放置一个虚拟声明。

AbcDll.AnyClass dummy006; // this will be enough to cause the DLL to be copied

您不需要为每个类都这样做——只需一次就足以使 DLL 复制并且一切都按预期工作。

附录:请注意,这可能适用于调试模式,但不适用于发布。有关详细信息,请参阅@nvirth 的答案。

【讨论】:

这似乎是一个 hack。添加对主项目的引用似乎就足够了。 这是一个 hack,但正如今天的 CodeProject 新闻告诉我们的那样,即使是编译器也可能出错! 事情有多疯狂。 @OverlordZurg 您的解决方案有效,因为我在我的 XAML(WPF)中引用了依赖 dll,并且它没有将 DLL 复制到主项目,直到我按照您所说的添加一个简单的虚拟引用......无论如何谢谢 @MohsenAfshin 我遇到了同样的问题——我在 XAML 中引用了一个依赖 DLL。然而,我没有声明一个虚拟变量,而是简单地命名了我在 XAML 中使用的组件,这足以导致其程序集被复制。 @MikeK 将它添加到主项目(实际上并不直接依赖它)是一个更大的黑客,imo。然后你必须在两个地方管理它(“管理”,如升级或删除)。使用 this hack,至少你会得到一个很好的编译时错误,提醒你在删除依赖项时删除这个 hack,你仍然只需要在一个地方更新它。【参考方案15】:

不确定这是否有帮助,但对我来说,很多时候我引用了一个 DLL(当然,它会自动将它添加到 bin 文件夹中)。但是,该 DLL 可能需要额外的 DLL(取决于我使用的函数)。我不想在我的项目中引用它们,因为它们只需要与我实际使用的 DLL 位于同一文件夹中。

我在 Visual Studio 中通过“添加现有文件”来完成此操作。您应该能够将它添加到除 Add_data 文件夹之外的任何位置。我个人只是将它添加到根目录。

然后将该文件的属性更改为...

Build Action = None(将此设置为 Content 之类的内容实际上会将“根”版本复制到根目录,以及 Bin 中的副本)。

复制到输出文件夹=如果较新则复制(基本上只有在丢失时才将其放入BIN文件夹,但之后不会这样做)

当我发布时……我添加的 DLL 仅存在于 BIN 文件夹中,而发布位置中的其他任何地方都不存在(这是我想要的)。

【讨论】:

【参考方案16】:

您还可以检查以确保您要查找的 DLL 不包含在 GAC 中。如果构建机器上的 GAC 中已经存在这些文件,我相信 Visual Studio 会很聪明地不复制这些文件。

我最近遇到了这种情况,我一直在测试一个需要在 GAC 中存在程序集的 SSIS 包。我已经忘记了这一点,并想知道为什么这些 DLL 在构建过程中没有出现。

检查 GAC 中的内容(来自 Visual Studio 开发人员命令提示符):

gacutil -l

或者输出到一个文件以便于阅读:

gacutil -l > output.txt
notepad.exe output.txt

要删除程序集:

gacutil -u MyProjectAssemblyName

我还应该注意,一旦我从 GAC 中删除了文件,它们就会在构建后正确地输出到 \bin 目录中(即使对于在根项目中没有直接引用的程序集)。这是在 Visual Studio 2013 Update 5 上。

【讨论】:

谢谢,你是对的,如果在 GAC 中找到 dll,MSBuild 不会将其复制到输出文件夹。【参考方案17】:

只是对 Zurg 大王的回答的一个旁注。

我以这种方式添加了虚拟引用,它在调试模式下工作:

public class DummyClass

    private static void Dummy()
    
        var dummy = typeof(AbcDll.AnyClass);
    

但在发布模式下,依赖的 dll 仍然没有被复制。 但是这有效:

public class DummyClass

    private static void Dummy()
    
        Action<Type> noop = _ => ;
        var dummy = typeof(AbcDll.AnyClass);
        noop(dummy);
    

这个信息实际上花了我几个小时才弄清楚,所以我想我分享一下。

【讨论】:

在发布模式下,优化器假定“dummy”没有被使用,所以这一行是不必要的,应该被删除。但是当你在代码中使用“dummy”时,优化器不会认为这是不必要的。 这对我不起作用。AbcDll.AnyClass 仍然没有复制到其他项目 确保 AbcDll.AnyClass 被用作公共类的公共字段或属性,然后它将起作用。如果你在这样的方法体中使用它,编译器不会看到它。它会延迟加载这个程序集,而不是你想要发生的事情。【参考方案18】:

您可以将主项目和ProjectX的构建输出路径设置为同一个文件夹,然后您可以在该文件夹中获取您需要的所有dll。

【讨论】:

【参考方案19】:

遇到了同样的问题。背景信息:在构建之前,我在解决方案中添加了一个新的 Project X。 Y项目依赖X项目,A、B、C项目依赖Y项目。

构建错误是找不到项目 A、B、C、Y 和 X dll。

根本原因是新创建的 Project X 以 .NET 4.5 为目标,而其余解决方案项目以 .NET 4.5.1 为目标。 Project X 未构建,导致其余项目未构建构建任何一个。

确保任何新添加的项目都以与解决方案的其余部分相同的 .NET 版本为目标。

【讨论】:

引用的项目可能是旧版本的 .NET。我可以通过为 .NET 4.5 构建的项目引用为 .NET 4 构建的项目。【参考方案20】:

是的,您需要将 Copy Local 设置为 true。但是,我很确定您还需要从主项目中引用该程序集,并将 Copy Local 设置为 true - 它不只是从依赖程序集中复制的.

您可以通过单击References 下的程序集并按F4 来访问Copy Local 属性。

【讨论】:

@Brij,该程序集是从您想要的 主项目 中引用的吗?正如我所说,我很确定您也需要从该项目中引用 - 依赖程序集不会像那样复制。如果是这种情况,您在使用 NuGet 时不需要将程序集添加到所有相关项目中。 @mcmillab,简而言之,Visual Studio 不会推断来自其他依赖项目的依赖关系。如果项目 A 引用项目 B,则项目 A 需要拥有项目 B 的所有引用。当所有项目 B 需要的是 .NET 程序集时,它可以很好地工作,但如果它是第 3 方程序集,则必须添加对两个项目的引用。 @MichaelPerrenoud 我认为这不是真的。如果您查看详细的 MSBuild 输出,您将看到对 ResolveAssemblyReference 的调用,其中声明它“包括二阶和 n 阶依赖项”。这也与我在 bin 文件夹中看到的一致(第 n 个依赖项被复制)。问题是对复制的内容有一些警告,主要是围绕 GAC 和间接引用(添加引用有时还不够) 我目前的经验是,对于“复制的”依赖项,这将起作用 except:项目 A.net 将外部 C++ dll 引用为“始终复制”的文件。项目 B.net 引用项目 A。在构建时,B/Debug 包括 C++ dll。但是,当我构建引用项目 B 的应用程序 X 时,C++ dll 有时 会被复制(似乎只有在我进行重建时才会复制)。 我很确定这是错误。它不需要推断依赖项,它只需要复制输出(从一个项目的bin到另一个项目的bin),MSBuild至少在正常情况下会这样做。

以上是关于从属 DLL 未复制到 Visual Studio 中的生成输出文件夹的主要内容,如果未能解决你的问题,请参考以下文章

DLL 注入编译“未解析的外部符号”Visual Studio C++

如何让 Visual Studio 将 DLL 文件复制到输出目录?

Visual Studio:将依赖的 DLL 复制到目标文件夹

使用 Visual Studio 2015、C++ 项目的 DLL 没有“复制到输出目录”

在 Visual Studio 中复制 DLL 的依赖项

如何设置 Visual Studio 以将所需的 DLL 文件复制到发布版本中的发布目录中?