microsoft / VSExtensibility

A repo for upcoming changes to extensibility in Visual Studio, the new extensibility model, and language server protocol.
MIT License
370 stars 48 forks source link

When using custom object sources, the `DebuggerVisualizerProviderConfiguration` property must not have a backing store. #310

Open aetos382 opened 10 months ago

aetos382 commented 10 months ago

Debugger Visualizer extensions with custom object sources require the DebuggerVisualizerProviderConfiguration property of the visualizer provider to create and return a new object each time.

Reproduction steps:

  1. Clone this repository and open solution.
  2. Start debugging, open the appropriate project and visualize a variable of some string type.
  3. If you open Good Visualizer or Simple Visualizer, the dialog will appear normally.
  4. If you open Bad Visualizer, you will see the following error message in the dialog. image

At this time, the following error occurs internally.

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.VisualStudio.DebuggerVisualizers, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Could not find file
File name: 'Microsoft.VisualStudio.DebuggerVisualizers, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.VisualStudio.DebuggerVisualizers, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Could not find file
File name: 'Microsoft.VisualStudio.DebuggerVisualizers, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, RuntimeAssembly requestingAssembly, Boolean throwOnFileNotFound)
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(AssemblyName assemblyName)
   at Microsoft.ServiceHub.HostLib.ServiceLoadContext.LoadAssemblyFromDefaultContext(AssemblyName assemblyName)
   at Microsoft.ServiceHub.HostLib.ServiceLoadContext.Load(AssemblyName assemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingLoad(AssemblyName assemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName)
   at VisualizerExtension.BadVisualizerProvider..ctor()
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.VisualStudio.Extensibility.DefaultMessagePackServiceFactory.CreateAsync(ServiceMoniker serviceMoniker, ServiceActivationOptions activationOptions, IServiceProvider serviceProvider, AuthorizationServiceClient authorizationServiceClient, Type instanceType, Type interfaceType, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Extensibility.ExtensionCore.CreateAsync(IServiceProvider hostProvidedServices, ServiceMoniker serviceMoniker, ServiceActivationOptions serviceActivationOptions, IServiceBroker serviceBroker, AuthorizationServiceClient authorizationServiceClient, CancellationToken cancellationToken)
   at Microsoft.ServiceHub.HostStub.Utilities.InvokeMethodIfObjectImplementsInterfaceAsync(Object obj, Type implementedInterface, String methodName, Object[] parameters, Boolean throwOnError)
   at Microsoft.ServiceHub.HostStub.ServiceManager.InvokeServiceHubServiceFactory(AssemblyName serviceHubFramework, Object serviceFactory, Object[] args, String serviceHubServiceFactoryTypeName, String methodName)
   at Microsoft.ServiceHub.HostStub.ServiceManager.<>c__DisplayClass69_0.<<CreateServiceModuleObjectWithFactoryAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.ServiceHub.Framework.ServiceManagerReflectionHelpers.SetupRpcConnectionAsync(Func`2 getRpcObject, Stream stream, ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options, TraceSource traceSource, Action`1 completionTask)

Please fix the behavior so that such errors do not occur, or guide us to define the property without backing store via analyzer.

matteo-prosperi commented 9 months ago

The issue here is that the extension doesn't package Microsoft.VisualStudio.DebuggerVisualizers.dll which can be sourced from C:\Program Files\Microsoft Visual Studio\2022\xxx\Common7\IDE\PublicAssemblies. This is because the Microsoft.VisualStudio.DebuggerVisualizers only contains reference assemblies which are not sufficient when a type referenced in the extension (in this case ObjectSource) had a dependency on Microsoft.VisualStudio.DebuggerVisualizers.dll.

@aetos382, FYI, GoodVisualizer is not failing because the DebuggerVisualizerProviderConfiguration property getter is never invoked.

@mpeyrotc, I will open an internal bug for this. We should either publish real assemblies in the Microsoft.VisualStudio.DebuggerVisualizers in the nuget package (the object source project can use ExcludeAssets="runtime" if necessary). Or we could add Microsoft.VisualStudio.DebuggerVisualizers as one of the shared dependencies of the extension host.