microsoft / VSProjectSystem

Documentation for extending Visual Studio with new types of projects.
Other
313 stars 87 forks source link

IDynamicDebugTargetsGenerator not registered in VS 2022 #349

Open emrekultursay opened 2 years ago

emrekultursay commented 2 years ago

We have a Visual Studio extension that customizes the debug button using IDynamicDebugTargetsGenerator. The extension has been working fine for VS 2017 and 2019 for several years. I am now porting it to VS 2022.

In VS 2022, my class with the [Export(typeof(IDynamicDebugTargetsGenerator))] attribute never gets instantiated. Therefore, debug button customizations do not work. Here is a simplified version of the code:

TargetsGenerator.cs:

    [AppliesTo(AndroidConfiguredProject.Capability)]
    [Export(typeof(IDynamicDebugTargetsGenerator))]
    [ExportMetadata("Name", "TargetsGenerator")]
    internal class TargetsGenerator : ProjectValueDataSourceBase<IReadOnlyList<IEnumValue>>, IDynamicDebugTargetsGenerator
    {
        [ImportingConstructor]
        public TargetsGenerator(UnconfiguredProject project) : base(project.Services)
        {
              // THIS CONSTRUCTOR IS NEVER CALLED IN VS 2022.
        }
        public override NamedIdentity DataSourceKey { get; } = new NamedIdentity(nameof(TargetsGenerator));
        public override IComparable DataSourceVersion => 0;
        public override IReceivableSourceBlock<IProjectVersionedValue<IReadOnlyList<IEnumValue>>> SourceBlock
        { get { return null; } }
    }

    [ExportDynamicEnumValuesProvider("DebugTargetEnumValuesProvider")]
    [AppliesTo(AndroidConfiguredProject.Capability)]
    internal class DebugTargetEnumValuesProvider : IDynamicEnumValuesProvider, IDynamicEnumValuesGenerator
    {
            // This part is not very relevant. but I'm adding the class here for completeness.
    }

android_debugger.xaml:

<Rule
    Name="GoogleAndroidDebugger"
    DisplayName="Android Game Development Extension Debugger"
    PageTemplate="debugger"
    Description="Android Game Development Extension Debugger options"
    xmlns="http://schemas.microsoft.com/build/2009/properties"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <!-- irrelevant parts deleted -->

    <Rule.Metadata>
        <sys:Guid x:Key="DebugTargetTypeCommandGuid">568ABDF7-D522-474D-9EED-34B5E5095BA5</sys:Guid>
        <sys:UInt32 x:Key="DebugTargetTypeCommandId">0x100</sys:UInt32>
        <sys:String x:Key="DebugTargetDropdownEnum">AndroidDebugTargetProvider</sys:String>
    </Rule.Metadata>

    <DynamicEnumProperty Name="AndroidDebugTargetProvider" DisplayName="Debug Target Provider"
                         EnumProvider="TargetsGenerator"
                         Description="Specifies the Android device to use for debugging"
                         Visible="True">
        <DynamicEnumProperty.DataSource>
            <DataSource Persistence="UserFile" HasConfigurationCondition="False" SourceOfDefaultValue="AfterContext" />
        </DynamicEnumProperty.DataSource>
    </DynamicEnumProperty>

    <!-- skipping irrelevant parts -->
</Rule>

In VS 2019, the constructor above is called before the async package is loaded. The part of the stack trace looks like this:

mscorlib.dll!System.Lazy<Microsoft.VisualStudio.ProjectSystem.Debug.IDynamicDebugTargetsGenerator>.CreateValue()    Unknown
mscorlib.dll!System.Lazy<Microsoft.VisualStudio.ProjectSystem.Debug.IDynamicDebugTargetsGenerator>.LazyInitValue()  Unknown
mscorlib.dll!System.Lazy<Microsoft.VisualStudio.ProjectSystem.Debug.IDynamicDebugTargetsGenerator>.Value.get()  Unknown
Microsoft.VisualStudio.ProjectSystem.dll!Microsoft.VisualStudio.ProjectSystem.MefExtensions.ExtensionValues<Microsoft.VisualStudio.ProjectSystem.Debug.IDynamicDebugTargetsGenerator>(System.Collections.Generic.IEnumerable<System.Lazy<Microsoft.VisualStudio.ProjectSystem.Debug.IDynamicDebugTargetsGenerator>> extensions, bool onlyCreatedValues) Unknown

The ProjectSystem.dll version is 16.09.579.5755 on 2019, and 17.00.1313.5288 on VS 2022.

drewnoakes commented 2 years ago

Do you see anything in the MEF error log?

%LocalAppData%\Microsoft\VisualStudio\17.0_<code>Exp\ComponentModelCache\Microsoft.VisualStudio.Default.err

You may need to experiment to find <code>, and you'll only need Exp if you're F5-ing in VS and using the experimental hive.

drewnoakes commented 2 years ago

Also, does it work if you use the capability "LaunchProfiles" instead of AndroidConfiguredProject.Capability? Perhaps there's a timing issue where your capability is excluding the item at the point they're constructed because the capability is not yet active.