如何在Template Wizard中获取IVsPackageInstaller实现动态NuGet安装?
问题:IWizard中如何通过AutomationObject获取IVsPackageInstaller动态安装NuGet包
我有VS模板及模板向导,在IWizard的RunStarted实现里,Visual Studio提供了AutomationObject。现有方案都提到通过IComponentModel.GetService获取NuGet.VisualStudio的IVsPackageInstaller,但我无法获取IComponentModel引用,将automationObject强制转换为IComponentModel也失败了,请问怎么在IWizard实现中(通过automationObject)连接到IVsPackageInstaller来动态安装NuGet包?
补充代码
以下是Microsoft.VisualStudio.TemplateWizard程序集中的IWizard基础代码:
public class MyWizard : IWizard { public DTE Application { get; private set; } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { this.Application = automationObject as DTE; replacementsDictionary["$safeitemname$"] = "newitemcode.cs"; } public void ProjectFinishedGenerating(Project project) { /* n/a for item generation */ } public void ProjectItemFinishedGenerating(ProjectItem projectItem) { IVsSolution sol = this.Application.Solution as IVsSolution; if (sol != null) { InstallNugetPackages(); } } private void InstallNugetPackages() { IComponentModel host = this.Application as IComponentModel; //<-- 这里失败,host为null IVsPackageInstaller installer = host.GetService<IVsPackageInstaller>(); } public bool ShouldAddProjectItem(string filePath) { throw new NotImplementedException(); } public void BeforeOpeningFile(ProjectItem projectItem) { throw new NotImplementedException(); } public void RunFinished() { throw new NotImplementedException(); } }
解决方案
核心思路
AutomationObject本质是DTE对象,无法直接转换为IComponentModel。需要通过DTE获取VS的服务容器,再从中获取IComponentModel实例,进而拿到IVsPackageInstaller。
步骤及修改后的代码
添加必要引用
- 引用
Microsoft.VisualStudio.Shell.Immutable.10.0(或更高版本) - 安装并引用
NuGet.VisualStudioNuGet包
- 引用
修改向导代码
调整ProjectItemFinishedGenerating和InstallNugetPackages方法,正确获取服务并安装包:
using Microsoft.VisualStudio.Shell; using NuGet.VisualStudio; using Microsoft.VisualStudio.OLE.Interop; // 保留原有其他引用 public class MyWizard : IWizard { public DTE Application { get; private set; } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { this.Application = automationObject as DTE; replacementsDictionary["$safeitemname$"] = "newitemcode.cs"; } public void ProjectFinishedGenerating(Project project) { /* n/a for item generation */ } public void ProjectItemFinishedGenerating(ProjectItem projectItem) { // 直接从ProjectItem获取所属项目,无需转换IVsSolution if (projectItem?.ContainingProject != null) { InstallNugetPackages(projectItem.ContainingProject); } } private void InstallNugetPackages(Project targetProject) { // 通过DTE创建服务提供者 var serviceProvider = new ServiceProvider((IServiceProvider)this.Application); // 获取IComponentModel实例 IComponentModel componentModel = serviceProvider.GetService<SComponentModel, IComponentModel>(); if (componentModel == null) return; // 获取IVsPackageInstaller IVsPackageInstaller installer = componentModel.GetService<IVsPackageInstaller>(); // 示例:安装指定版本的Newtonsoft.Json包 installer?.InstallPackage( sourceRepository: null, // 使用默认NuGet源 project: targetProject, packageId: "Newtonsoft.Json", version: "13.0.3", ignoreDependencies: false ); } public bool ShouldAddProjectItem(string filePath) { throw new NotImplementedException(); } public void BeforeOpeningFile(ProjectItem projectItem) { throw new NotImplementedException(); } public void RunFinished() { throw new NotImplementedException(); } }
注意事项
- 确保向导项目的目标框架与Visual Studio版本兼容
- 如果需要自定义NuGet源,可以修改
InstallPackage方法的sourceRepository参数 - 处理好异常情况(比如包不存在、网络问题等),避免向导崩溃
内容的提问来源于stack exchange,提问作者JaedenRuiner
相关产品推荐
相关产品推荐

