结合使用 VisualStudio.Extensibility SDK 和 VSSDK
虽然 VisualStudio.Extensibility 模型主要是为了在devenv.exe进程之外托管扩展,但可以在 Visual Studio 进程中运行的扩展中使用 VisualStudio.Extensibility SDK API,并利用 Microsoft.VisualStudio.Sdk 包提供的传统扩展性 API。
支持过程内使用旨在允许早期采用者使用新的 VisualStudio.Extensibility API,同时依赖 Microsoft.VisualStudio.Sdk 来涵盖任何功能差距。
本文档是有关使用 VisualStudio.Extensibility SDK in-proc 的不同选项的快速演练。
如果要开发新的扩展,建议的方法是创建本教程后面的进程内托管的 VisualStudio.Extension。 使用此方法,除了能够注入 VSSDK 和 MEF 服务外,还可以使用 VisualStudio.Extensibility SDK 的完整功能。
如果有现有的 VSSDK 扩展,可以按照 以下提示 在扩展中使用新的 VisualStudioExtensibility 实例。
如果要使用 VisualStudio.Extensibility SDK 将命令、调试可视化工具窗口、工具窗口添加到现有 VSSDK 扩展,可以参考 这些提示 来托管 VSSDK 扩展和同一 VS 扩展项目中的 VisualStudio.Extensibility 扩展。
创建首个与 VSSDK 兼容的 VisualStudio.Extensibility 扩展
虽然 VisualStudio.Extensibility 模型主要是为了在devenv.exe进程之外托管扩展,但从 Visual Studio 2022 17.4 预览版 1 开始,可以生成一个托管在devenv.exe内的 VisualStudio.Extensibility 扩展性扩展插件,并且可以使用 Microsoft.VisualStudio.Sdk 包提供的传统扩展性 API。
先决条件
- 具有
Visual Studio extension development
工作负载的 Visual Studio 2022 版本 17.9 预览版 1 或更高版本。 - 如果要从早期版本更新,请确保卸载 VisualStudio.Extensibility Project System 以避免潜在的冲突。
创建扩展项目
- 使用 VisualStudio.Extensibility Extension with VS SDK Compatibility template 创建新的解决方案。
调试扩展
将 容器 项目设置为 启动项目,按
F5
开始调试。按按
F5
生成扩展并将其部署到正在使用的 Visual Studio 版本的实验实例。 加载扩展后,调试器应附加。可以在菜单中找到命令
Extensions
,如下图所示:
从 VisualStudio.Extensibility 扩展使用 Visual Studio SDK 服务
与 VS-SDK 兼容的扩展项目引用 Microsoft.VisualStudio.Sdk 包,该包允许访问所有 Visual Studio SDK 的服务。
传统上,此类服务通过 MEF 或 AsyncServiceProvider 使用。 建议使用 VisualStudio.Extensibility 扩展程序注入 .NET 依赖项。
类MefInjection<TService>
AsyncServiceProviderInjection<TService, TInterface>
(来自Microsoft.VisualStudio.Extensibility.VSSdkCompatibility
命名空间)允许通过将它们添加到通过依赖项注入实例化的类的构造函数(如命令、工具窗口或扩展部件)来使用 Visual Studio SDK 的服务。
以下示例演示如何 DTE2
将服务和 IBufferTagAggregatorFactoryService
服务添加到命令。
[VisualStudioContribution]
public class Command1 : Command
{
private TraceSource traceSource;
private AsyncServiceProviderInjection<DTE, DTE2> dte;
private MefInjection<IBufferTagAggregatorFactoryService> bufferTagAggregatorFactoryService;
public Command1(
VisualStudioExtensibility extensibility,
TraceSource traceSource,
AsyncServiceProviderInjection<DTE, DTE2> dte,
MefInjection<IBufferTagAggregatorFactoryService> bufferTagAggregatorFactoryService)
: base(extensibility)
{
this.dte = dte;
this.bufferTagAggregatorFactoryService = bufferTagAggregatorFactoryService;
}
public override CommandConfiguration CommandConfiguration => new("Sample Remote Command")
{
Placements = new[] { CommandPlacement.KnownPlacements.ExtensionsMenu },
Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText),
};
VSSDK 兼容的 VisualStudio.Extensibility 扩展的剖析
虽然将 VisualStudio.Extensibility Extension 与 VS SDK 兼容性模板配合使用负责设置整个解决方案,但了解 VS-SDK 兼容的 VisualStudio.Extensibility 扩展插件的基本组件与“创建第一个扩展”指南中所述的常见变体有何不同,这非常有用。
容器项目
VS-SDK 兼容的 VisualStudio.Extensibility 解决方案由两个项目组成:
- 引用 VisualStudio.Extensibility 和 Visual Studio SDK 包并包含扩展的所有代码的类库,
- 用于部署和调试扩展的容器 VSIX 项目。
此分离是临时解决方案,而 VisualStudio.Extensibility 处于预览状态,最终打包和部署设计正在完成。
扩展程序不应将代码、内容或资源添加到容器项目。 容器项目的唯一目标是包括其他项目提供的资产。
TargetFramework
扩展项目和容器项目都必须面向目标 Visual Studio 版本使用的 .NET 版本。 对于 Visual Studio 2022,它们必须面向 .NET Framework 4.7.2。
RequiresInProcessHosting 属性
Extension
必须使用将扩展标识为进程内的属性来配置RequiresInProcessHosting = true
该类。
[VisualStudioContribution]
internal class MyExtension : Extension
{
public override ExtensionConfiguration? ExtensionConfiguration => new()
{
RequiresInProcessHosting = true,
};
...
使用现有 VSSDK 扩展中的 VisualStudio.Extensibility
对于现有的 VSSDK 扩展,另一个选项是通过服务提供商查询 VisualStudioExtensibility 实例并利用其方法。 此方法允许在现有组件中使用 VisualStudio.Extensibility SDK 的新 API 外围应用。 在想要使用新 API 查询项目信息、文档管理而不创建新的基于 VisualStudio.Extensibility 的扩展的情况下,此选项非常有用。
下面是一个示例代码片段,演示如何在 VisualStudioExtensibility
VSSDK 包中使用:
.csproj
在文件中,包括对 VisualStudio.Extensibility API 的包引用:
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Extensibility" Version="17.9.23-preview-1" />
</ItemGroup>
- 现在可以通过
GetServiceAsync
包或其他组件中的方法查询 VisualStudioExtensibility 实例:
...
using Microsoft.VisualStudio.Extensibility;
...
public class VSSDKPackage : AsyncPackage
{
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
VisualStudioExtensibility extensibility = await this.GetServiceAsync<VisualStudioExtensibility, VisualStudioExtensibility>();
await extensibility.Shell().ShowPromptAsync("Hello from in-proc", PromptOptions.OK, cancellationToken);
...
}
}
向现有 VSSDK 扩展项目添加 VisualStudio.Extensibility 扩展
如果还想要在现有 VSSDK 扩展内使用 VisualStudio.Extensibility SDK 的编辑器侦听器(如工具窗口)提供组件,则必须按照其他步骤在项目中创建 VisualStudio.Extensibility Extension 实例。
需要使用 SDK 样式
.csproj
才能使用 VisualStudio.Extensibility SDK 包。 对于现有项目,可能需要将自己的.csproj
SDK 样式更新为 SDK 样式。删除 VisualStudio.Extensibility 的
Microsoft.VSSDK.BuildTools
包引用,并改为添加包引用。
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.9.23-preview-1" />
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.9.23-preview-1" />
- 将属性添加到
VssdkCompatibleExtension
项目文件,将其设置为true
. 此属性将启用一些 VSSDK 功能以实现兼容性。
<PropertyGroup>
<VssdkCompatibleExtension>true</VssdkCompatibleExtension>
</PropertyGroup>
- 创建继承自
Extension
基类的新扩展类,并设置 RequiresInProcessHosting 属性,如前所示。
现在,可以将 VisualStudio.Extensibility 的所有功能与现有的 VSSDK 扩展一起使用。