以编程方式更新Visual Studio项目引用

9
我希望以编程方式更新Visual Studio解决方案中项目的引用。
我的解决方案中大约有15个项目,当我开发/调试时,我希望引用指向解决方案中的项目。
作为发布程序的一部分,有时我需要复制一个项目,并将引用更新为指向特定文件夹中构建的dll。
我可以了解项目文件的结构以及其中的引用如何工作,我正在考虑构建一个命令行工具来解析项目文件并根据需要更改引用。
我的问题是:
1. 这听起来合理吗?
2. 有人有此经验和/或如何处理在开发和发布模式之间切换
3. 有没有任何库可以处理解析Visual Studio项目文件。
澄清:
感谢回答。也许我应该澄清一下我希望使用这个工具的一些情况。
a) 我的应用程序包含15个项目。我尽量使解决方案尽可能小,因此假设我的解决方案中有5个项目。现在我需要调试/开发不在解决方案中的一个项目,所以我添加了这个项目,但我必须:
- 将原始项目中的引用设置为指向项目引用而不是编译后的dll - 更改新添加项目中的引用以指向适当的项目引用
我希望我的工具可以自动完成这些操作,目前我知道的唯一方法是操作项目文件。
b) 作为服务包生成过程的一部分,我复制一个项目,进行必要的代码更改并在Visual Studio中构建。为此,我必须更改所有引用以指向编译后的dll。

Gary,你需要Thunk的VS版本! - Jon
6个回答

11

我认为更好的方法是直接在项目文件中使用条件块控制引用。然后只需在“release”构建期间设置特定标志,就可以自动选择正确的引用。

例如:

<ItemGroup Condition="'$(IsRelease)'=='True'">
  <Reference Include="..." />
</ItemGroup>
<ItemGroup Condition="'$(IsRelease)'!='True'">
  <Reference Include="..." />
</ItemGroup>

是的,这看起来比我的答案好;) - Steve Cooper
请原谅我的无知,但这两者不都等于true吗?即:如果它等于true或者它不是false。也许我只是漏掉了什么。 - user18411
@Jeremy,你没有错过任何东西。我在最后一秒改变了条件,并没有回顾整个答案。已修复。 - JaredPar

1
我认为第一个问题并没有简单的答案。通常情况下,我建议避免这种情况。它很难手动处理,并且管理它的代码并不是微不足道的。
话虽如此,在我的工作中,我遇到了一种问题,我根本无法解决。在我们的情况下,我们正在努力发布一个SDK,其中需要包括一组示例项目。那些项目的“开发”版本既使用了项目引用,又使用了对第三方库的引用。
这带我们来到第三点,基本上是肯定的。事实上,我曾经发布过一个 开源项目,其中包含一个库、一个简单的 Windows 实用程序和一个 NAnt 扩展,可以自动将项目引用更改为 dll 引用。实际上,它还处理将那些第三方库移动到同一个本地文件夹并更新项目文件中的这些引用。
这个解决方案并不完美,我想要添加很多改进,但它确实适用于我们的情况。我们的发布脚本的一部分(全部在 NAnt 中)运行此过程,以将所有引用交换到相对路径。然后我们就可以轻松地打包整个设置。也许有一天,我会抽出时间添加一个 MSBuild 任务和项目。

我认为尽可能避免这种情况是最好的,但如果像我一样卡住了 - 我发布的代码至少应该会有所帮助。


1
欢迎来到Stack Overflow!感谢您发布答案!请注意,您应该在这个网站上发布答案的有用部分,否则您的帖子可能会被删除请参阅FAQ中提到的“几乎只是链接”的答案。如果您愿意,仍然可以包含链接,但只作为“参考”。答案应该能够独立存在,不需要链接的支持。 - Andrew Barber

1

老虎,老虎咆哮!!!

这是使用DTE和VSProject来编程式添加引用。我已经对大部分代码进行了注释以进行解释。但是为了添加方便,我添加了许多不同的额外引用,因为我有点懒。但只要在Visual Studio中进行排序,你应该就没问题了。如果由于任何原因无法编译,请随时向我喊话。

使用System; 使用System.Collections.Generic; 使用System.ComponentModel; 使用System.Linq; 使用System.Runtime.InteropServices; 使用System.Text; 使用System.Windows.Forms; 使用EnvDTE; 使用EnvDTE80; 使用EnvDTE90; 使用EnvDTE90a; 使用Extensibility; 使用Microsoft.VisualStudio.Shell; 使用Microsoft.VisualStudio.Shell.Design; 使用Microsoft.VisualStudio.Shell.Interop; 使用VSLangProj;
命名空间ConsoleApplication2 { class Program { static void Main(string[] args) { //免责声明: //我是通过扩展来完成这个操作的,获取DTE的引用可能与您的方式不同, //因为有几种不同的方法可以实现。但是VSProject应该不会有问题。
//获取DTE引用,我正在使用EnvDTE80中的DTE2 //我还没有深入研究最早兼容的版本是什么 //包是Microsoft.VisualStudio.Shell.Package DTE2 _appObject = Package.GetGlobalService(typeof(DTE)) as DTE2;
//这将获取解决方案集中的第一个项目,并将其转换为VSProject //请注意,Web项目使用不同的类型,类似于VSWebProject或其他我忘记的东西... var pj = (VSProject)_appObject.Solution.Projects.Item(1).Object;
//您的dll路径 pj.References.Add(@"c:\MyRefs\Pastry.dll"); } } }

1
虽然这不是你问题的完整答案,但我认为展示如何在代码中简单实现可能会有所帮助。 - Terrance
1
这绝对是太棒了,谢谢!顺便说一下,如果你想添加支持(VSProject)转换的引用,请在“引用管理器”中搜索“lang”,然后添加VSLangProj和VSLangProj110(如果使用Visual Studio 2012)。 - Contango

0

0

0

听起来有点奇怪。

我的建议是这样的。

  1. 将具有预构建版本的项目拆分为单独的解决方案。将它们全部构建到

    \assemblies\fromsource

  2. 将预构建的项目复制到;

    \assembly\prebuilt

  3. 在开发其余项目之前,将任一目录复制到

    \assembly\development

  4. 更改您的项目以指向 \assembly\development 中的版本。

现在,您始终针对已知文件夹中的预编译二进制文件构建产品,因此您永远不需要更改项目。但是您可以随意在版本之间切换。

对于额外的加分,将预构建事件更改为在开始构建之前复制 dll,并根据配置使源文件夹变化。然后在 DEBUG 和 RELEASE 旁边添加一个 PREBUILT 配置。


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