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


185

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

现在,应将此abc.dll复制到主项目的bin / debug文件夹中,但不会在此处复制它。任何已知原因为何未复制它?


如果您无法解决此问题,则将其复制到预构建版本中。
Dilshod

您如何在主项目中使用“ ProjectX”-项目,目标等的类型是什么?
NSGaga-mostly-inactive 2013年

我遇到了同样的问题,这个答案解决了我的问题:stackoverflow.com/a/8213977/174469
Gordon Tucker 2013年


RestoreProjectStyle 可用的解决方案。这个想法是为<RestoreProjectStyle>PackageReference</RestoreProjectStyle>解决方案中的每个.Net Framework项目设置。
oleksa,

Answers:


105

我发现,如果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的答案。


7
这似乎是hack。将引用添加到主项目似乎就足够了。
Mike K

3
这是一个hack,但是正如今天的CodeProject新闻告诉我们的那样,即使编译器也可能是错误的!
祖尔格Zurg 2015年

4
事情有多疯狂。@OverlordZurg您的解决方案可以正常工作,因为我在XAML(WPF)中引用了相关的dll,并且直到您添加了一个简单的虚拟引用后,它才将DLL复制到主项目中……无论如何
Mohsen Afshin

5
@MohsenAfshin我遇到了同样的问题-我在XAML中引用了一个依赖的DLL。但是,我没有声明虚拟变量,而是简单地命名了我在XAML中使用的组件,这足以导致其程序集被复制。
redcurry

5
@MikeK将它添加到主项目(实际上并不直接依赖于它)是一个更大的技巧imo。然后,您必须在两个位置进行管理(在升级或删除中为“管理”)。有了这个 hack,至少您会收到一个不错的编译时错误,提醒您在删除依赖项时也要删除此hack,而您仍然只需要在一个地方进行更新。
jpmc26 2016年

70

只是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);
    }
}

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


6
在发布模式下,优化程序假定未使用“虚拟”,因此该行是不必要的,应将其删除。但是当您在代码中使用“虚拟”时,优化器不会认为没有必要。
Yucel

1
这对我不起作用。AbcDll.AnyClass仍未复制到其他项目
Matthew Lock

3
确保AbcDll.AnyClass用作公共字段或公共类的属性,然后它将起作用。如果在这样的方法主体中使用它,编译器不会看到它。它将延迟加载此程序集,而不是您想要发生的事情。
约翰·莱德格伦

52

是的,您需要设置Copy Localtrue。不过,我敢肯定,你还需要从主体工程和一套装配参考Copy Local,以true以及-它不只是得到从依赖程序集复制。

您可以Copy Local通过单击下面的装配References并按F4 来进入属性。


2
@Brij,程序集是从您要包含在其中的主项目中引用的吗?正如我所说,我非常确定您也需要从该项目中引用-依赖程序集不会像这样被复制。在这种情况下,使用NuGet时无需将程序集添加到所有相关项目中。
Mike Perrenoud

1
这里的结论是什么?在我看来,您是对的-即使CopyLocal设置为true,也不会复制依赖的引用-其背后的逻辑是什么?
mcmillab

29
@mcmillab,简而言之,Visual Studio不会从其他依赖项目推断出依赖关系。如果项目A引用了项目B,则项目A将需要具有项目B的所有引用。当所有项目B都需要.NET程序集时,它可以很好地工作,但是如果它是第三方程序集,则必须将引用添加到两个项目中。
Mike Perrenoud 2013年

12
@MichaelPerrenoud我认为那不是真的。如果查看详细的MSBuild输出,将看到对ResolveAssemblyReference的调用,该调用声明其“包括第二和第n阶依赖项”。这也与我在bin文件夹中看到的一致(第n个依赖项被复制)。问题是有一些关于复制内容的警告,主要是关于GAC和间接引用(有时添加引用有时是不够的)
Jack Ukleja 2014年

2
我目前的经验是,除了 “已复制”的依赖项,这将起作用:项目A.net将外部C ++ dll引用为“始终复制”的文件。项目B.net参考项目A。在生成时,B / Debug包括C ++ dll。但是,当我构建引用项目B的应用程序X时,有时会复制C ++ dll (似乎仅当我进行重建时)。
Benjol '02

33

将其设置为装配体属性时看起来很漂亮

[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已经被复制而没有属性。
JS

25

遇到同样的问题。背景信息:在构建之前,我已经向解决方案中添加了一个新的ProjectX。项目Y取决于项目X,项目A,B,C取决于项目Y。

生成错误是找不到Project A,B,C,Y和X dll。

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

确保所有新添加的项目都与该解决方案的其余部分使用相同的.NET版本。


1
引用的项目可能是.NET的旧版本。我可以通过为.NET 4.5构建的项目引用为.NET 4构建的项目。
redcurry

18

不确定是否有帮助,但对我而言,我多次引用DLL(当然会自动将其添加到bin文件夹中)。但是,该DLL可能需要其他DLL(取决于我使用的功能)。我不想在我的项目中引用它们,因为它们只需要与我实际使用的DLL放在同一文件夹中即可。

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

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

Build Action = None(将其设置为类似Content的内容实际上将“ root”版本复制到root,再在Bin中复制一个副本)。

复制到输出文件夹=如果较新则复制(基本上仅在丢失时将其放在BIN文件夹中,但此后不这样做)

当我发布..时,我添加的DLL仅存在于BIN文件夹中,而在发布位置(我想要的)中没有其他位置。


10

您还可以检查以确保所需的DLL不包含在GAC中。我相信Visual Studio在不复制那些文件(如果在构建计算机上的GAC中已经存在)方面很聪明。

我最近遇到这种情况,当时我正在测试一个SSIS程序包,该程序需要在GAC中存在程序集。从那以后,我就忘记了这一点,并且想知道为什么这些DLL在构建期间没有出现。

要检查GAC中的内容(通过Visual Studio Developer命令提示符):

gacutil -l

或输出到文件以使其更易于阅读:

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

要删除程序集:

gacutil -u MyProjectAssemblyName

我还应注意,一旦从GAC中删除了文件,它们在构建后便会正确输出到\ bin目录中(即使对于在根项目中未直接引用的程序集也是如此)。这是在Visual Studio 2013更新5上进行的。


谢谢,您是对的,如果MSBuild在GAC中找到dll,则不会将dll复制到输出文件夹。
约翰·菲利普

3

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

由于添加dll作为对主项目的引用无效,因此我决定将其添加为“现有项”,并且“复制本地=始终”。即使那样,文件也不在那里。

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

之所以愚蠢,是因为我在VS领域从事开发已有15年了。我之前碰到过这个问题,我只是不记得了,以某种方式我错过了它,因为由于文件是常规引用,所有内容仍在编译中,但是作为现有项添加的文件并未被复制,因为它不存在源代码控制服务器。

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


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

2

这是对nvirth的示例的轻微调整

internal class DummyClass
{
    private static void Dummy()
    {
        Noop(typeof(AbcDll.AnyClass));
    }
    private static void Noop(Type _) { }
}

2

我会将其添加到Postbuild事件中,以将必要的库复制到输出目录。类似于XCopy pathtolibraries targetdirectory

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


这对我有用,我认为这是更好的答案。虚拟参考解决方案是可行的,但这是一个技巧,而构建后规则是实现相同结果的一种干净方法。
凯文·费希特

2

问题:

NuGet包DLL(Newtonsoft.json.dll)遇到类似的问题,其中生成输出不包含引用的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/


1

代码中不需要傻瓜
只是:

添加对可执行项目的引用

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


1

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

在此处输入图片说明


1
复制LOAL被禁用,这有助于stackoverflow.com/questions/15526491/...
codemirror

1

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

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

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

特别:

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

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

我决定通过添加Microsoft.Extensions.Logging.Console来解决此问题Project2,只是发现Visual Studio的Nuget Manager未列出Microsoft.Extensions.Logging.Console安装位置。Project1Project1.csproj文件,尽管该文件中存在该文件。

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


实际上,我以测试方式重新启动了整个PC,但它对我
有用

0

您可以将主项目和ProjectX的build输出路径都设置到同一文件夹,然后可以在该文件夹中获得所需的所有dll。


0

确保您使用的从属dll的目标.net框架没有高于项目应用程序的目标.net框架。

您可以通过选择项目,然后按ALT + ENTER,然后从左侧选择Application,然后选择项目的Target Framework来进行检查。

假设从属dll目标框架= 4.0,应用程序dll目标框架= 3.5,然后将其更改为4.0

谢谢!


0

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

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.