从属 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的可能重复 有RestoreProjectStyle
solution 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>
我手动删除了<Private>True</Private>
行,然后在每次构建主项目时将 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 复制到目标文件夹