Usando o SDK do VisualStudio.Extensibility e o VSSDK juntos

Embora o modelo VisualStudio.Extensibility tenha sido criado principalmente para hospedar extensões fora do processo de devenv.exe, é possível usar APIs do SDK do VisualStudio.Extensibility em uma extensão em execução no processo do Visual Studio e utilizando APIs de extensibilidade tradicionais fornecidas pelos pacotes Microsoft.VisualStudio.Sdk.

O suporte do uso em processo destina-se a permitir que os adotantes iniciais das novas APIs VisualStudio.Extensibility, enquanto dependem do Microsoft.VisualStudio.Sdk para cobrir qualquer lacuna de recursos.

Este documento é um passo a passo rápido sobre diferentes opções para utilizar o SDK do VisualStudio.Extensibility em processo.

  • Se você estiver desenvolvendo uma nova extensão, nosso método recomendado é criar uma VisualStudio.Extension hospedada em execução no processo seguindo este tutorial. Esse método permite que você use recursos completos do SDK visualStudio.Extensibility, além de poder injetar serviços VSSDK e MEF.

  • Se você tiver uma extensão existente do VSSDK, poderá seguir essas dicas para usar a nova instância do VisualStudioExtensibility na sua extensão.

  • Se você quiser adicionar comandos, visualizadores de depuração, janelas de ferramentas à sua extensão existente do VSSDK usando o SDK VisualStudio.Extensibility, você pode consultar essas dicas para hospedar uma extensão VSSDK e uma extensão VisualStudio.Extensibility no mesmo projeto de extensão do VS.

Crie sua primeira extensão VisualStudio.Extensibility compatível com VSSDK

Embora o modelo VisualStudio.Extensibility tenha sido criado principalmente para hospedar extensões fora do processo de devenv.exe, começando com o Visual Studio 2022 17.4 Preview 1, é possível criar uma extensão VisualStudio.Extensibility hospedada no devenv.exe e pode usar APIs de extensibilidade tradicionais fornecidas pelo pacotes de Microsoft.VisualStudio.Sdk.

Pré-requisitos

  • Visual Studio 2022 versão 17.9 Versão Prévia 1 ou superior com a carga de trabalho Visual Studio extension development.
  • Se você estiver atualizando de builds anteriores, desinstale o VisualStudio.Extensibility Project System para evitar possíveis conflitos.

Criar o projeto de extensão

  • Use o modelo Extensão VisualStudio.Extensibility com compatibilidade com o VSSDK para criar uma solução.

pt-BR: Captura de tela do modelo de projeto de extensão em processo VisualStudio.Extensibility.

Depurar sua extensão

  • Pressione F5 para iniciar a depuração, isso compila sua extensão e a implanta na instância experimental da versão do Visual Studio que você está usando. O depurador deve ser anexado depois que a extensão for carregada.

  • Você pode encontrar o comando no menu Extensions conforme mostrado na imagem a seguir:

    Captura de tela mostrando o comando de extensão de exemplo.

Consumo de serviços do SDK do Visual Studio em uma extensão do VisualStudio.Extensibility

Um projeto de extensão compatível com VS-SDK faz referência ao pacote Microsoft.VisualStudio.Sdk, que permite acesso a todos os serviços do SDK do Visual Studio.

Tradicionalmente, esses serviços são consumidos por meio de MEF ou AsyncServiceProvider. Em vez disso, um extensor VisualStudio.Extensibility é incentivado à injeção de dependência do .NET.

As classes MefInjection<TService> e AsyncServiceProviderInjection<TService, TInterface> (ambas do namespace Microsoft.VisualStudio.Extensibility.VSSdkCompatibility) permitem consumir os serviços do SDK do Visual Studio adicionando-os ao construtor de uma classe que é instanciada por meio de injeção de dependência (como um comando, uma janela de ferramenta ou uma parte de extensão).

O exemplo a seguir mostra como os serviços de DTE2 e IBufferTagAggregatorFactoryService podem ser adicionados a um comando.

    [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),
        };

Anatomia de uma extensão VisualStudio.Extensibility compatível com VSSDK

Ao usar a extensão VisualStudio.Extensibility com o modelo de compatibilidade VSSDK, que cuida da configuração completa do projeto, é útil saber quais são os componentes básicos de uma extensão VisualStudio.Extensibility compatível com o VS-SDK e como ela difere da variante comum descrita no guia "criar sua primeira extensão" .

TargetFramework e VssdkCompatibleExtension

O projeto de extensão deve ter como destino a versão do .NET usada pela versão de destino do Visual Studio. Para o Visual Studio 2022, eles devem ter como destino o .NET Framework 4.7.2.

O projeto de extensão também deve conter a propriedade VssdkCompatibleExtension definida como true.

<PropertyGroup>
  <VssdkCompatibleExtension>true</VssdkCompatibleExtension>
</PropertyGroup>

Propriedade RequiresInProcessHosting

A classe Extension deve ser configurada com a propriedade RequiresInProcessHosting = true que identifica a extensão como sendo em processo.

[VisualStudioContribution]
internal class MyExtension : Extension
{
    public override ExtensionConfiguration? ExtensionConfiguration => new()
    {
        RequiresInProcessHosting = true,
    };

    ...

Manifesto do pacote

O projeto de extensão deve incluir um manifesto do pacote chamado source.extension.vsixmanifest. A tag Installation deve ter ExtensionType definida como VSSDK+VisualStudio.Extensibility.

<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
    <Metadata>
        <Identity Id="MyExtensionId.f14b8c45-154f-4584-abd7-9ec22af003e2" Version="1.0" Language="en-US" Publisher="Microsoft" />
        <DisplayName>My extension</DisplayName>
        <Description xml:space="preserve">My extension's description.</Description>
    </Metadata>
    <Installation ExtensionType="VSSDK+VisualStudio.Extensibility">
        <InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.9,18.0)">
            <ProductArchitecture>amd64</ProductArchitecture>
        </InstallationTarget>
      <InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.9,18.0)">
        <ProductArchitecture>arm64</ProductArchitecture>
      </InstallationTarget>
    </Installation>
    <Prerequisites>
        <Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[17.0,)" DisplayName="Visual Studio core editor" />
    </Prerequisites>
    <Assets>
        <Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
    </Assets>
</PackageManifest>

Usar VisualStudio.Extensibility nas extensões existentes do VSSDK

Para extensões existentes do VSSDK, outra opção é consultar a instância VisualStudioExtensibility por meio do provedor de serviços e utilizar seus métodos. Esse método permite que você use a nova área de superfície da API do SDK VisualStudio.Extensibility em seus componentes existentes. Essa opção pode ser útil em situações em que você gosta de usar a nova API para consultar informações do projeto, gerenciamento de documentos sem criar uma nova extensão baseada em VisualStudio.Extensibility.

Este é um exemplo de snippet de código que mostra como se pode utilizar VisualStudioExtensibility dentro de um pacote VSSDK:

  • No seu arquivo .csproj, inclua uma referência de pacote para as APIs do VisualStudio.Extensibility.
  <ItemGroup>
    <PackageReference Include="Microsoft.VisualStudio.Extensibility" Version="17.9.2092" />
  </ItemGroup>
  • Agora você pode consultar a instância VisualStudioExtensibility por meio do método GetServiceAsync no pacote ou em outros componentes:
...
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);
        ...
    }
}

Adicionar uma extensão VisualStudio.Extensibility a um projeto de extensão do VSSDK existente

Se você também quiser contribuir com componentes como janelas de ferramentas e ouvintes do editor, usando o SDK VisualStudio.Extensibility nas extensões existentes do VSSDK, precisará seguir etapas adicionais para criar uma instância Extensão do VisualStudio.Extensibility no projeto.

  • Você precisa de um estilo de SDK .csproj para utilizar pacotes do SDK do VisualStudio.Extensibility. Para projetos existentes, talvez seja necessário atualizar o .csproj para o estilo SDK.

  • Remova a referência de pacote para Microsoft.VSSDK.BuildTools e, em vez disso, adicione referências de pacote para VisualStudio.Extensibility.

    <PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.9.2092" />
    <PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.9.2092" />
  • Adicione VssdkCompatibleExtension propriedade ao arquivo de projeto, definindo-a como true. Essa propriedade habilitará alguns recursos do VSSDK para compatibilidade.
<PropertyGroup>
    <VssdkCompatibleExtension>true</VssdkCompatibleExtension>
</PropertyGroup>    
  • Crie uma nova classe de extensão herdando da classe base Extension e defina a propriedade RequiresInProcessHosting, conforme mostrado anteriormente.
  • Modifique o arquivo source.extension.vsixmanifest adicionando ExtensionType="VSSDK+VisualStudio.Extensibility" à tag Installation.
<Installation ExtensionType="VSSDK+VisualStudio.Extensibility">

Agora você pode usar todos os recursos do VisualStudio.Extensibility junto com a extensão existente do VSSDK.