Solucionar problemas de serviços intermediados
Aplica-se a: Versões posteriores e do Visual Studio 2019
Este artigo apresenta sugestões de solução de problemas e possíveis soluções para vários problemas comuns que podem ocorrer quando você tenta obter um serviço intermediado no SDK do Visual Studio.
Os serviços intermediados podem falhar de várias maneiras. Uma técnica útil para iniciar sua investigação é marcar o Log de Atividades do Visual Studio, que geralmente registra erros ou avisos quando as coisas dão errado com serviços intermediados.
Problemas ao solicitar um serviço
Talvez o desafio mais comum com serviços intermediados seja entender o resultado ou a exceção que eles recebem de uma chamada para IServiceBroker.GetProxyAsync ou IServiceBroker.GetPipeAsync. Um IServiceBroker abstrai intencionalmente as preocupações sobre onde e como um serviço intermediado pode ser ativado. Mas quando as coisas dão errado, torna-se necessário aprofundar-se para diagnosticar e corrigir o problema.
Nenhum serviço
O resultado de uma solicitação de serviço pode ser null
quando qualquer uma das seguintes condições for verdadeira:
- O serviço solicitado não está registrado. O autor do serviço intermediado deve registrá-lo com ProvideBrokeredServiceAttribute ou um arquivo .pkgdef criado à mão.
- O serviço solicitado é registrado com configuração que não expõe o serviço a esse cliente. O escopo padrão é ServiceAudience.Process, o que significa que o serviço intermediado só pode ser ativado quando ele é oferecido do mesmo processo que o cliente. Se o cliente estiver em outro processo e a intenção for que o serviço intermediado esteja disponível para ele, altere o registro de serviço para expandir seu ServiceAudience.
- O serviço solicitado é registrado com ServiceAudience.LiveShareGuest, existe uma conexão live share, mas o host não oferece esse serviço intermediado ou a ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients propriedade não está definida como
true
. Ao expor um serviço intermediado pelo Live Share, examine Como proteger um serviço intermediado. - O serviço solicitado está registrado, mas não há informações sobre qual pacote será inicializado para que sua fábrica possa ser oferecida. O ProvideBrokeredServiceAttribute atributo gera automaticamente o registro que indica o pacote ao qual o atributo foi aplicado para que o Visual Studio possa carregar esse pacote conforme necessário. Se o atributo for aplicado ao pacote errado ou o arquivo .pkgdef for criado à mão, essas informações poderão estar ausentes ou imprecisas.
- O pacote do Visual Studio responsável por oferecer o serviço intermediado é lançado durante a inicialização ou, de outra forma, não oferece essa fábrica de serviços. Verifique o Log de Atividades do Visual Studio para obter evidências de uma falha de carga do pacote.
- A própria fábrica de serviços retorna
null
.
A solicitação de serviço gera uma exceção
Uma solicitação de serviço pode gerar um ServiceCompositionException quando o service factory gera uma exceção. Isso significa que todos os problemas listados acima que levariam a um null
resultado não se aplicam. Examine os detalhes da exceção (incluindo exceções internas) para entender o que deu errado e fazer as correções necessárias ao cliente ou ao service factory.
Você obtém um serviço local enquanto um remoto era esperado
Uma solicitação pode ser atendida local ou remotamente, dependendo do registro do serviço e do estado atual do Visual Studio. O escopo padrão é ServiceAudience.Process, o que significa que o serviço intermediado só pode ser ativado quando ele é oferecido do mesmo processo que o cliente.
Quando um serviço intermediado deve ser exposto de um host do Live Share a um convidado conectado, mas ServiceAudience limitado a escopos locais, uma solicitação de um convidado do Live Share ativará o serviço intermediado desse mesmo computador em vez do host. Atualize o registro para incluir ServiceAudience.LiveShareGuest para expor seus serviços intermediados pelo Live Share. Você também pode precisar definir ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients como true
também.
Importante
O registro do serviço intermediado deve existir tanto no convidado do Live Share quanto no host para dar suporte ao convidado na ativação do serviço intermediado do host.
Ao expor um serviço intermediado pelo Live Share, examine Como proteger um serviço intermediado.
Problemas ao oferecer um serviço
Um serviço intermediado deve ser oferecido de uma AsyncPackage classe, a menos que o serviço intermediado seja exportado via MEF, conforme descrito em Como fornecer um serviço intermediado.
Uma tentativa de oferecer um serviço intermediado gerará uma exceção se alguma dessas condições for verdadeira:
- O moniker para o serviço que está sendo oferecido não corresponde exatamente (nome e versão) a um serviço que foi registrado.
- Uma fábrica já foi oferecida para o mesmo moniker de serviço.
O resultado de uma chamada para IBrokeredServiceContainer.Proffer é um IDisposable. Um serviço intermediado fica indisponível para novas solicitações depois que esse valor é descartado. Quando o serviço intermediado tem afinidade específica com algum contexto, como uma solução aberta, pode ser apropriado oferecer apenas o serviço intermediado quando esse contexto estiver ativo. Não é necessário reter e descartar esse valor quando o pacote for descartado.
Rastreamento de RPC entre cliente e serviço
Depois que uma conexão entre cliente e serviço é estabelecida, o rastreamento de sua comunicação pode ser útil, especialmente quando eles estão em processos diferentes.
Por padrão, os rastreamentos de comunicações entre serviços intermediados que abrangem processos (de modo que o RPC se aplica) são registrados em arquivos .svclog encontrados no %TEMP%\VSLogs
diretório. Esses arquivos xml são melhor exibidos com o Visualizador de Rastreamento de Serviço. Essa ferramenta pode abrir muitos arquivos .svclog ao mesmo tempo e costurá-los juntos para formar um grafo multipartidário para facilitar muito a compreensão do RPC entre cliente e serviço.
Um serviço intermediado em si pode rastrear diretamente para adicionar a esses arquivos de rastreamento .svclog, auxiliando ainda mais diagnóstico do comportamento do serviço intermediado. Todos os rastreamentos salvos podem %TEMP%\VSLogs
ser coletados quando o comando "Relatar um problema" for invocado e o usuário optar por compartilhar logs.
Para rastrear suas próprias mensagens de modo que elas possam ser facilmente descobertas e combinadas com outros rastreamentos .svclog , seu código (se um serviço intermediado ou não) pode fazer algo assim:
// Define your log's ID, a namespace-like fully qualified name.
// In general it is expected that you follow you team's assembly namespace.
// Also an optional parameter, the ServiceMoniker for your service
var myLogId = new LogId("Microsoft.SomeTeam.MyLogName", serviceId: null);
var requestedLevel = new LoggingLevelSettings(SourceLevels.Warning | SourceLevels.ActivityTracing);
var myLogOptions = new LoggerOptions(requestedLevel, PrivacyFlags.MayContainPrivateInformation);
TraceSource myTraceSource;
using (TraceConfiguration traceConfig = await TraceConfiguration.CreateTraceConfigurationInstanceAsync(serviceBroker, ownsServiceBroker: false, cancellationToken))
{
myTraceSource = await traceConfig.RegisterLogSourceAsync(myLogId, myLogOptions, traceSource: null, cancellationToken);
}
O myTraceSource
agora pode ser usado para rastreamento, pois tem os ouvintes apropriados adicionados para gravar seus rastreamentos em um arquivo .svclog . Se você já tiver um TraceSource que deseja usar, passe-o para o RegisterLogSourceAsync método e descarte o resultado, pois os ouvintes serão adicionados ao seu existente TraceSource.
Ao rastrear um serviço intermediado que atende a um cliente remoto, uma atividade é atribuída automaticamente ao que seu ExecutionContext código é executado dentro que permite que o svclog seja costurado junto com o svclog do cliente, a fim de ver uma exibição holística usando o Visualizador de Rastreamento de Serviço.