Today, we’re very excited to announce the third public preview of VisualStudio.Extensibility, our new SDK for creating extensions for Visual Studio!
The VisualStudio.Extensibility SDK focuses on extensions that run out-of-process from the IDE for improved performance and reliability, and it features a modern API that has been streamlined and carefully engineered to maximize developer productivity.
This release builds on our first and second public previews, and it brings some big features like an API to query and modify project information and the ability to create incredible debugger visualizers. Please visit the VisualStudio.Extensibility repo to find docs and installation instructions. You can also use our issue tracker to report bugs and provide feedback.
What’s new for Preview 3 of VisualStudio.Extensibility?
The VisualStudio.Extensibility Preview 3 release expands your ability to create powerful productivity extensions, with features including:
- Debugger Visualizers
- Custom Dialogs
- Query the Project System
- Editor Margin Extensions
- Configure your Extension
Create custom data visualizers for better debugging
Debugger visualizers, such as the popular IEnumerable visualizer, add tremendous power to the debugging experience in Visual Studio by enabling custom views of complex data types. With this release, we’ve leveraged our Remote UI features to enable you to create debugger visualizers with VisualStudio.Extensibility!
We can’t wait to see the debugger visualizers you create with this feature!
Interact with users through custom dialogs
With the last release of VisualStudio.Extensibility, you could interact with users through prompts with simple, configurable buttons. Now, you can go beyond buttons and interact with your users through dialogs featuring custom UI.
Dialogs are backed by our Remote UI features, so you can use WPF to create rich, interactive visuals, and then you can show your dialog to the user with a simple call:
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
using IRemoteUserControl content = new MyDialogControl();
await this.Extensibility.Shell().ShowDialogAsync(content, "My Dialog", DialogOption.Close, cancellationToken);
}
Sample code for showing a custom dialog
Query the project system for information about projects and solutions
With the latest preview, we’ve added the ability to query the project system for projects in a solution that match a set of conditions or for information about those projects. For example, you could use this query API to detect that web projects are present in the solution before enabling web-related commands in your extension:
IQueryResults<IProjectSnapshot> webProjects = await Extensibility.Workspaces().QueryProjectsAsync(
project => project.Where(p => p.Capabilities.Contains("DotNetCoreWeb"))
.With(p => new { p.Path, p.Guid }),
cancellationToken);
Sample code for finding all the projects in a solution with a given set of capabilities.
You could also modify projects, for example by adding a project reference or creating a new file:
await Extensibility.Workspaces().UpdateProjectsAsync(
project => project.Where(p => p.Name == "MyProject"),
project => project.CreateFile("NewFile.txt", newFileContents),
cancellationToken);
Sample code for adding a new text file to a project
With these features, your extension can deliver experiences to your users that feel directly relevant to the code they’re working on!
Add valuable context with editor margin extensions
We know developers spend most of their time in Visual Studio working with files and documents in the editor. With editor margin extensions, you can get your work in front of many users by leveraging Remote UI to create great front-and-center experiences that boost developer productivity. You could use this feature to offer simple at-a-glance features like the word count or the encoding of the open document, but you could also create custom navigation bars or headers!
Configure your extension easily with configuration properties
Many components defined in your extensions require you to configure how or when they appear in the IDE. For example, if you define a command, you could configure it to be a menu item in the Tools menu or an icon on the toolbar. If you define a tool window, you could configure it to be either docked or floating.
Based on feedback from user testing, we’ve completely overhauled extension configuration for better discoverability and usability. Now, you’ll be able to configure your extension with strongly-typed classes and properties, and you’ll have IntelliSense to help you discover and browse predefined options. These changes will help you get your extensions to work like you intend them to.
With the changes, configuration has gone from looking like this with attributes:
[Command(
"VisualStudio.Extensions.MarkdownLinter.RunLinterOnActiveDocument",
"Run Linter on open file",
containerType: typeof(MarkdownLinterExtension),
placement: CommandPlacement.ToolsMenu)]
[CommandEnabledWhen(
"FileSelected",
new string[] { "FileSelected" },
new string[] { "ClientContext:Shell.ActiveSelectionFileName=.+" })]
[CommandIcon("MarkdownIcon", IconSettings.IconAndText)]
internal class RunLinterOnCurrentFileCommand : Command
Command configuration using the old configuration attributes
to looking like this with configuration properties:
[VisualStudioContribution]
internal class RunLinterOnCurrentFileCommand : Command
{
public override CommandConfiguration CommandConfiguration => new("%RunLinterOnCurrentFileCommand.DisplayName%")
{
Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu },
Icon = new(ImageMoniker.Custom("MarkdownIcon"), IconSettings.IconAndText),
EnabledWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveSelectionFileName, ".+"),
};
...
}
Command configuration using the new configuration properties
Control the placement of your commands
As seen in the configuration properties above, you can easily place your commands inside known menus, but you can also place them inside new menus and toolbars, which you can create and control:
[VisualStudioContribution]
public static ToolbarConfiguration MyToolbar => new ToolbarConfiguration("%MyToolbar.DisplayName")
{
Children = new[]
{
ToolbarChild.Command<MyCommand>(),
},
}
Sample code for creating a toolbar with a command
Add keyboard shortcuts to your commands
Now you can set keyboard shortcuts for your commands using simple sets of keys and modifiers:
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
Shortcuts = new CommandShortcutConfiguration[]
{
new(ModifierKey.ControlShift, Key.G),
},
};
Sample code for setting a keyboard shortcut for a command
We can’t do this without you!
As we continue to develop VisualStudio.Extensibility, we need your help! Please give Preview 3 a try and share your thoughts with us. You can give feedback, report bugs, make suggestions, and ask questions through our issue tracker. You can also sign up here to be contacted about future user studies, which are invaluable as we work to give you the best possible experience with our SDK.
Please go to the VisualStudio.Extensibility repo for docs, code samples, and setup instructions so you can get started today!
Has any consideration been giving to performance profiling of VS extensions? One of the biggest challenges I have run into is having the environment slowed down by some sort of extension and not knowing which one is overusing resources, or why it's overusing them.
Optimization of extensions is critical to ensuring a smooth and positive experience, and giving more tools to allow insight into this for extension developers would be amazing.
An example I've given in the...
Very excited to see that Visualizers are finally part of the extension model! Looking forward to trying this out. Are there any docs available yet on how to do this?
Debugger Visualizers are one of the most exciting features of the new release! We have both docs and a sample in the VisualStudio.Extensibility repo. Like many of our features, debugger visualizers leverage our WPF-based remote UI framework, so I'd recommend you look at our UI docs as well.
Appreciate seeing these updates and blog posts! VSExtensibility is still a huge market and it definitely needs more love!
As an aside, I'd love to see more involvement from the MS folks involved at the community level. VSCode has a strong Slack presence with members from that MS team, and we need something like that for VS. I find the old "gitter" stuff to be quite lack-luster and out of style when it comes to communication...
Hi Calvin and thank you for your interest in VisualStudio.Extensibility! We’re excited that you’re excited, and we’re committed to delivering a great extensibility experience!
Our engineers are working hard on the features for our next release, so for now the best place to connect with them and to provide feedback or request features is the Issues page for the VisualStudio.Extensibility repo. As the project moves forward, we’re planning for more ways to be involved with the...
I created a Slack workspace. If you’re interested in VS Extensibility, feel free to join!
https://join.slack.com/t/vsextensibility/shared_invite/zt-1qg4lh99e-slSv9u_ZV7Whs0hUEQQGUg