Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Debugger extension for C++ #343

Open
golf89 opened this issue Jul 6, 2021 · 2 comments
Open

Custom Debugger extension for C++ #343

golf89 opened this issue Jul 6, 2021 · 2 comments

Comments

@golf89
Copy link

golf89 commented Jul 6, 2021

I am trying to Custom Debugger extension for my own C++ project, i have tried step mentioned at https://github.com/microsoft/VSProjectSystem/blob/master/doc/extensibility/IDebugLaunchProvider.md by creating XAML file and extending DebugLaunchProviderBase and providing enum value to be displayed.

But as soon as i load the template i see 4 default options (local windows debugger, remove windows debugger, web service debugger, web browser debugger).

even if i try to run the project i don't get call into my own Implementation of LaunchAsync in DebugLaunchProviderBase child class.

Can anyone suggest what i am missing?

I have applied the project capability to all the classes in sample extension and to vcxproj also.

to summarise

I am trying to create my own debugger implementation for c++ projects so that I can get my custom label on debug button and can handle the debugging/launch of the program.

Thanks in Advance

@jobmarley
Copy link

jobmarley commented Feb 14, 2022

Hey,

that's a bit late, but I ran into the same kind of issues. And after quite a bit of investigation I was able to understand what's going on.
So first, the c++ project system doesn't load the debugger extension on project load (I don't even know if it happens with other project types). If you want your extension to be loaded, you can use
[Export(ExportContractNames.Scopes.ConfiguredProject, typeof(IProjectDynamicLoadComponent))]
If you do that you will see that the LoadAsync/UnloadAsync are called if you have the right capability (you can try with "VisualC").

Even though that's unintuitive, the list of available debuggers is not defined by the exported MEF debuggers, but by the rules registered for the project.
When you click the debug button, the exported IDebugLaunchProvider are enumerated and the one with a matching name is instanciated and CanLaunchAsync, etc... are called.
Now the issue is the documentation suggest that we use ExportPropertyXamlRuleDefinition, but I wasn't able to make that work at all (in vs 2022).
The best way in my opinion is to use IProjectDynamicLoadComponent. Then import a IAdditionalRuleDefinitionsService in the constructor, and add the rule manually.
Then your debugger will appears in the drop down menu.

[Export(ExportContractNames.Scopes.ConfiguredProject, typeof(IProjectDynamicLoadComponent))]
[ExportDebugger("MyDebugger")]
[AppliesTo("VisualC")]
public class MyDebugLaunchProvider
	: DebugLaunchProviderBase,
	IProjectDynamicLoadComponent
{
	private ConfiguredProject m_configuredProject = null;

	[ImportMany(ExportContractNames.VsTypes.IVsHierarchy)]
	private OrderPrecedenceImportCollection<IVsHierarchy> IVsHierarchies { get; set; }

	[ImportingConstructor]
	public MyDebugLaunchProvider(ConfiguredProject configuredProject, IAdditionalRuleDefinitionsService rds)
		: base(configuredProject)
	{
		IVsHierarchies = new OrderPrecedenceImportCollection<IVsHierarchy>(projectCapabilityCheckProvider: configuredProject.UnconfiguredProject);
		m_configuredProject = configuredProject;
		Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("XamlRuleToCode:MyDebugger.xaml");
		Rule rule = ((IProjectSchemaNode)XamlServices.Load(stream)).GetSchemaObjects(typeof(Rule)).Cast<Rule>().FirstOrDefault();
		rds.AddRuleDefinition(rule, "Project");
	}

	public override Task<bool> CanLaunchAsync(DebugLaunchOptions launchOptions)
	{
		// perform any necessary logic to determine if the debugger can launch
		return Task.FromResult(true);
	}

	public override async Task<IReadOnlyList<IDebugLaunchSettings>> QueryDebugTargetsAsync(DebugLaunchOptions launchOptions)
	{
		var settings = new DebugLaunchSettings(launchOptions);

		settings.LaunchDebugEngineGuid = DebuggerEngines.NativeOnlyEngine;

		settings.AppPackageLaunchInfo = new VsAppPackageLaunchInfo();
		settings.Arguments = "";
		settings.CurrentDirectory = "<exedir>";
		settings.Executable = "<exepath>.exe";
		settings.LaunchOperation = DebugLaunchOperation.CreateProcess;
		settings.LaunchOptions = launchOptions;
		settings.Options = "";
		settings.PortName = "";
		settings.PortSupplierGuid = Guid.Empty;
		settings.ProcessId = 0;
		settings.ProcessLanguageGuid = Guid.Empty;
		settings.Project = IVsHierarchies.FirstOrDefault()?.Value;
		settings.RemoteMachine = "";
		settings.SendToOutputWindow = false;
		settings.StandardErrorHandle = IntPtr.Zero;
		settings.StandardInputHandle = IntPtr.Zero;
		settings.StandardOutputHandle = IntPtr.Zero;

		return new IDebugLaunchSettings[] { settings };
	}

	public async Task LoadAsync()
	{
			
	}
	public async Task UnloadAsync()
	{
	}
}

Hopefully that might help you or others who run into the same issue.

@svenbieg
Copy link

I have some DesignTime.props

  <ItemGroup>
    <ProjectCapability Include="CustomDebugger" />
  </ItemGroup>

and DesignTime.targets

  <ItemGroup>
    <PropertyPageSchema Include="Rules\CustomDebugger.xaml" />
  </ItemGroup>

like shown in the CpsExtension-example. The Debugger shows up in the UI and the DLL is loaded, but DebugLaunchProvider isn't invoked.

I've added the code above

[Export(ExportContractNames.Scopes.ConfiguredProject, typeof(IProjectDynamicLoadComponent))]

but it does nothing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants