如何让Visual Studio在构建时解析并包含项目的所有依赖项?

21

我目前有一个大型的解决方案,在VS2010下,有很多项目和依赖项。其中一些已安装到GAC中,另一些则只是从“lib”文件夹中包含进来的。我需要构建我的其中一个项目(特别是WinForms应用程序),以便在任何非开发计算机上运行,而不需要进行任何安装过程(当然除了.NET运行时),就像可移植应用程序一样。

为了使这个功能正常工作,我需要在我的EXE的输出文件夹中拥有所有引用的DLL及其整个依赖树。例如,我可以通过将依赖项标记为“Copy local”来完成,但这仅适用于EXE项目的直接引用,因此远远不足够。另一种方法是创建安装项目,但我的客户和我也想避免这种情况(在最终版本中,我将使用ClickOnce)。当然,我总是可以通过手动方式来完成,手动收集所有的DLL,但那将是一场噩梦。

是否有一些工具、msbuild技巧、命令行选项或其他操作,可以强制Visual Studio在构建期间收集我的EXE的整个依赖树,并将它们复制到输出文件夹中?这样我就可以将所有文件压缩在一起发送给我的客户。

3个回答

1

基本上,使用Visual Studio,您可以将所有解决方案项目设置为构建到同一个输出文件夹中,并将此文件夹用作Windows窗体应用程序文件夹(应用程序EXE所在的位置)。

通过这样做,您将协调所有可能依赖于您的应用程序的程序集引用。

在VS 2012中,右键单击一个项目 => 属性 => 选择构建(左窗格) => 设置输出路径:

Output path in VS 2012

我会选择一个解决方案级别的文件夹作为“输出路径”。
如果在工作场所禁止执行此类修改,我建议您使用以下依赖分析工具来查询和收集应用程序所依赖且需要在运行时使用的适当程序集:
- Dependency Walker - NDepend - Red-Gate Reflector 更新:
使用上述工具将无法得到运行时绑定(late-bounded)的程序集引用。对于这种情况,您可以使用:Fusion (the Assembly Binding Log Viewer)

谢谢你,但正如你所写的,我没有可能做出这样一个全局性的更改。而且这甚至听起来也不是一个好的做法。我会检查你建议的工具,但可能会等一段时间,看看是否有更简单的方法。 - Zoltán Tamási
@ZoltánTamási 无论你要做什么,都要考虑到你的应用程序可能会使用延迟绑定来解决程序集 - 这是无法使用我提到的工具来确定的。请查看我的更新以获取有关延迟绑定的信息。 - Yair Nevet

1

实际上,我选择了一个有点“中间”的解决方案,如下所示。

  1. 我创建了一个“虚拟”安装项目,只关心添加项目输出(主要输出,本地化资源,内容等),不关心设置任何其他内容。这是一个两分钟的任务。
  2. 我构建了安装项目,并获得MSI文件作为输出。
  3. 我将MSI文件的内容提取到一个特定的文件夹中,例如“MyAppPortable”。我在这里找到了解决方案。命令行命令为

    msiexec /a“我的MSI输出的绝对路径”/qb TARGETDIR=“我的期望输出文件夹的绝对路径”

  4. 我得到了完整的应用程序及其所有已解析的依赖项(除了后期绑定的依赖项,但我通过将它们作为我的项目的引用手动添加来处理它们)。我可以将整个文件夹压缩,放在另一台计算机上,然后哇,一切都正常工作。


1
是的,因为安装程序项目包括所有内容(dlls、资源、PDBs,以及您添加到安装程序项目中的所有内容),用于完整的安装程序。我只是从MSI中“黑客式”提取了安装文件,就像正常的安装过程将它们放在程序文件夹中一样。 - Zoltán Tamási
你不能只是创建一个新文件夹,然后将所有所需的依赖文件复制进去吗?MSI 是如何帮助你的?它有什么附加价值?它是否为你自动化了一些操作?使用 MSI 的真正好处并不清楚——听起来就像是一个非常冗长的复制粘贴操作。 - Yair Nevet
1
问题是找到所有必需的文件。设置(或更一般地说,部署)项目可以递归地收集所有依赖的DLL、资源、内容文件,无论它们是否在GAC、"lib"文件夹、任何安装的第三方库或任何引用的项目中。所有这些东西都被打包成MSI文件。手动收集所有这些东西(即部署您的应用程序)是一场噩梦(我尝试过),并且会以许多方式引起错误(缺少DLLS、缺少内容文件或资源、不匹配的版本、平台等)。 - Zoltán Tamási
我所指的“添加”,是指在VS安装程序设计器中添加“MyWinformsProject”的“主输出”或“调试符号”等内容。 - Zoltán Tamási
1
可以配置设置项目以输出松散的文件,而不是输出 .msi 文件,从而节省提取的工作。 - Shiv
显示剩余4条评论

0

查看来自此问题的 Fody/Costura 推荐: 将 DLL 嵌入已编译的可执行文件中

太棒了!我刚刚尝试了类似需求的功能,不到几分钟就得到了一个完全可携带的(除了 .Net 框架)exe 文件,很容易地分享给同事们。


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