排查中转服务问题

适用于: Visual Studio 2019 及更高版本

本文介绍尝试在 Visual Studio SDK 中获取 中转服务 时可能出现的几个常见问题的故障排除建议和可能的解决方案。

中转服务可能以各种方式失败。 开始调查的一种有用方法是检查 Visual Studio 活动日志,该日志通常会在中转服务出现问题时记录错误或警告。

请求服务时出现的问题

中转服务的最常见挑战可能是了解它们通过调用 IServiceBroker.GetProxyAsync 或 获得的结果或 IServiceBroker.GetPipeAsync异常。 有意 IServiceBroker 地消除有关在何处以及如何激活中介服务的问题。 但是,当出现问题时,有必要更深入地钻取以诊断和更正问题。

无服务

当满足以下任何条件时,服务请求的结果可能 null 为 true:

  • 请求的服务未注册。 中转服务作者应将其注册到 ProvideBrokeredServiceAttribute 或手动创作的 .pkgdef 文件。
  • 请求的服务使用不向此客户端公开服务的配置进行注册。 默认范围为 ServiceAudience.Process,这意味着中转服务只有在从客户端的同一进程中提供时才能激活。 如果客户端位于另一个进程中,并且意图是让代理服务可供其使用,请更改服务注册以扩展其 ServiceAudience
  • 请求的服务注册到 ServiceAudience.LiveShareGuest,存在 Live Share 连接,但主机不提供该中转服务,或者 ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients 属性未设置为 true。 通过 Live Share 公开中介服务时,请查看 如何保护中转服务
  • 请求的服务已注册,但缺少有关要初始化哪个包的信息,以便可以提供其工厂。 属性 ProvideBrokeredServiceAttribute 自动生成注册,指示应用了该属性的包,以便 Visual Studio 可以根据需要加载该包。 如果属性应用于错误的包或 .pkgdef 文件是手动创作的,则此信息可能缺失或不准确。
  • 负责提供中转服务的 Visual Studio 包在初始化期间引发,否则无法实际提供该服务工厂。 检查 Visual Studio 活动日志 以获取包加载失败的证据。
  • 服务工厂本身返回 null

服务请求引发异常

服务工厂引发 ServiceCompositionException 异常时,服务请求可能会引发 。 这意味着上面列出的导致 null 结果的所有问题都不适用。 查看异常详细信息 (包括内部异常) ,以了解出了问题,并向客户端或服务工厂进行必要的更正。

你获得本地服务,而远程服务是预期的

可以根据服务注册和 Visual Studio 的当前状态,在本地或远程完成请求。 默认范围为 ServiceAudience.Process,这意味着中转服务只有在从客户端的同一进程中提供时才能激活。

当中转服务应从 Live Share 主机公开给连接的来宾,但 ServiceAudience 仅限于本地范围时,来自 Live Share 来宾的请求将激活来自同一台计算机而不是主机的中转服务。 更新要包括 ServiceAudience.LiveShareGuest 的注册,以通过 Live Share 公开中介服务。 可能还需要将 设置为 ProvideBrokeredServiceAttribute.AllowTransitiveGuestClientstrue

重要

Live Share 来宾和主机上必须同时存在代理服务的注册,以支持来宾从主机激活中转服务。

通过 Live Share 公开中介服务时,请查看 如何保护中转服务

提供服务时出现的问题

除非通过 MEF 导出中转服务,否则必须从 AsyncPackage 类中提供中 转服务,如如何提供中转服务中所述。

如果满足以下任一条件,尝试提供代理服务将引发异常:

  • 所提供服务的名字对象与已注册的服务) (名称和版本不完全匹配。
  • 已为同一服务名字对象提供了一个工厂。

调用 IBrokeredServiceContainer.Proffer 的结果是 IDisposable。 释放此值后,中转服务将变得对新请求不可用。 如果中转服务与某些上下文(如开放解决方案)具有特定相关性,则仅当该上下文处于活动状态时,才适合提供中转服务。 释放包时,无需保留和释放此值。

跟踪客户端和服务之间的 RPC

在客户端和服务之间建立连接后,跟踪其通信可能很有用,尤其是在它们处于不同进程中时。

默认情况下,跨进程 (RPC 应用) 的中转服务之间的通信跟踪记录记录在目录中的 %TEMP%\VSLogs.svclog 文件中。 最好使用 服务跟踪查看器查看这些 xml 文件。 此工具可以同时打开多个 .svclog 文件,并将它们拼凑在一起,形成多方图,以便更轻松地了解客户端和服务之间的 RPC。

中转服务本身可以直接跟踪以添加到这些 .svclog 跟踪文件,从而进一步帮助诊断中转服务行为。 当调用“报告问题”命令并且用户选择共享日志时,可能会收集保存到 %TEMP%\VSLogs 的任何跟踪。

若要跟踪自己的消息,以便可以轻松发现它们并将其与其他 .svclog 跟踪结合使用,代码 (中转服务是否) 可以执行如下操作:

// 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);
}

myTraceSource现在可用于跟踪,因为它添加了相应的侦听器,以便将跟踪写入 .svclog 文件。 如果已有 TraceSource 要使用的 ,请将其传递给 RegisterLogSourceAsync 方法并放弃结果,因为侦听器将添加到现有 TraceSource

从为远程客户端提供服务的中转服务进行跟踪时,会自动将 ExecutionContext 一个活动分配给代码运行的活动,该活动允许将 svclog 与客户端的 svclog 拼凑在一起,以便使用 服务跟踪查看器查看整体视图。

References