Visual Studio如何确定在多项目解决方案中将什么内容复制到输出目录?

31
假设我们有以下结构的解决方案:
  • Project.DAL - 数据访问层, 依赖于较低级别的库, 例如 Oracle.DataAccess w/copy local = true
  • Project.BLL - 业务逻辑层,引用 Project.DAL 作为项目
  • Project.UI - UI 层, 编译为可执行文件,引用 Project.BLL 作为默认项目
当编译 Project.UI 时,VS 足够智能,会将 Project.DAL.dll 复制到输出目录中,但它并不足够聪明,无法识别我希望 Oracle.DataAccess 也被复制到输出目录中以供客户端使用。
有人可以解释这是为什么吗? 是因为它看到了 GAC 中的 Oracle.DataAccess 并假设客户端也将其放在 GAC 中吗?
这不是什么大不了的事情,但每次添加新的程序集引用时,我都必须记住将其设置为“复制本地”并在我的构建脚本中添加一个复制项,这有点烦人。
4个回答

31

还有一件事情。

当你的代码中完全没有使用引用的 DLL,它会忽略 CopyLocal 并且不会将其复制到你的输出目录。


19
当您使用依赖注入并且没有直接引用任何特定的实现时,这会使事情变得很麻烦。嘿嘿! - kdawg
@SimonKarlsson 是的,但有点不太好,可以看看这些答案:https://dev59.com/nGUo5IYBdhLWcg3wtRbh#24828522 和 https://dev59.com/PXNA5IYBdhLWcg3wAIxP#21055664。我也想看到更好的解决方案。 - Herman Cordes
@hermancordes 感谢您的回复!不幸的是,这就是我最终解决它的方式。 - Simon Karlsson

27

是的,Visual Studio将在以下任何一种情况下将DLL复制到输出路径:

  1. DLL被明确引用并设置CopyLocal = true
  2. DLL未设置CopyLocal或通过其他引用的DLL隐式引用且不在全局程序集缓存(GAC)中

当文件存在于GAC中时,它为何不会进行本地复制?这是因为在解析程序集名称时,GAC具有最高优先级,即使您拥有(不同的)本地副本,也将使用来自GAC的版本。

我建议您设置一个库目录,将所有外部程序集放置其中,然后在没有将Oracle文件添加至GAC(也没有安装Visual Studio)的计算机(或虚拟机)上设置自动MSBuild脚本。这样,文件将被复制到生成目录,您将比使用VS时拥有更多控制权。


3
+1 强调“并且没有在GAC中”,这给我带来了一整天的问题。 - Oscar Foley
请注意,如果项目文件中未显式指定CopyLocal,则会使用CopyLocal的默认值。在VS 2015中,这个默认值最近发生了变化(connect.microsoft.com)! - Andreas
我该如何将一个例如xsd文件复制到输出文件夹?我无法直接在代码中引用xsd文件。 - Johannes
Visual Studio会在以下两种情况下将DLL复制到输出路径,您是指每个项目的输出路径还是主项目(例如Project.UI)的输出路径?当您设置CopyLocal=true时,DLL始终会被复制到输出路径(即使它存在于CAG中),但不会被复制到引用此项目的其他项目的输出路径。您还指出,“如果DLL未使用CopyLocal(您是否指CopyLocal=false?)并且不在GAC中”,则会被复制到输出路径,但如果CopyLocal=false,则DLL不会显示在输出路径中。 - Pedro Faustino

17

我遇到了一个奇怪的情况,即使程序集是项目引用,并且在引用属性窗口中显示“Copy Local”为“True”,但DLL文件未被复制到输出目录。我之前在GAC中有DLL文件的早期版本,但我不知道这应该防止DLL文件被复制。

我发现通过卸载项目并手动编辑项目引用的XML,如下所示:

<ProjectReference Include="..\SomeProject.csproj">
  <Project>{11111111-1111-1111-1111-111111111111}</Project>
  <Name>Some Project Name</Name>
  <Private>True</Private>
</ProjectReference>

预期DLL已经被复制到输出目录。 我发现,只需在属性窗口中将Copy Local设置为True,就意味着<Private>元素完全丢失了,但如果将其设置为false,则该元素存在并且值为“False”。


7
一种替代手动编辑.csproj文件的方法是将“复制本地”设置为False,然后执行“文件-全部保存”,再将“复制本地”设置为True并重新构建项目。 - RenniePet

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接