Notwithstanding the immense popularity of the Visual Studio Code programmer’s editor, the Visual Studio IDE is still at the heart of Microsoft’s development toolchain strategy. More than 25 years of evolution have brought us a customizable development environment that goes a long way beyond the original common UI for a set of development tools.
Today Visual Studio is a single application that dynamically loads the tools and languages needed to build your project. You can preconfigure toolchains, as well as pick and mix the features that help you deliver code. The result is a flexible development environment that supports modern development models, including remote development and shared code. There’s even support for the latest AI-powered coding assistants.
Key to that flexibility is Visual Studio’s extension model. It allows you to build your own tools that hook into the Visual Studio environment, using hooks in the UI and a built-in language server to add your own code highlighting and completion features. At the heart of this model is a toolkit that helps you get over the hurdles in extension development, with templates, API wrappers, and dedicated tools.
That extension model is changing. In 2021 I looked at how Visual Studio 2022 added support for 64-bit extensions, but there’s a lot more going on than supporting a larger address space. There’s more to be done to port existing extensions to the new environment, but porting progress has been good, and it should be possible to reassemble your usual toolchain in 64-bit form, ready for Visual Studio 2022.
The biggest changes to Visual Studio extensions are coming with a completely new extension model, now renamed VisualStudio.Extensibility. It changes the way extension code interacts with Visual Studio and reduces the risk of an extension crashing or hanging your IDE. It does this by allowing extensions to run outside the Visual Studio process, so if one crashes or pauses, it will not affect the host IDE.
Introducing a new extension model has allowed the Visual Studio team to deliver several important improvements. A new set of APIs has been refactored and redesigned to be simpler. Unfortunately for developers who used C++ to build extensions, the new model is .NET only. This change gives some advantages: New versions of an extension can be hot-loaded so you can update without restarting your entire development environment. They’re cross-platform and will run on the upcoming Arm release of Visual Studio without any rework. Using separate processes for extensions will eventually allow you to choose a trust level in a future Visual Studio release, for example, locking down file system access and limiting API calls to only those offered by Visual Studio.
Microsoft is taking a phased approach to rolling out this new extension model. The first phase, with support for out-of-process extensions for use with open documents, shipped in September 2021. The second phase has now arrived, nearly a year later. It won’t be the last, either; full compatibility with the older extension model is not expected until after the next major release of Visual Studio. Such a slow route may seem odd, but it makes sense as Visual Studio is such an important part of the Microsoft ecosystem that any issues, no matter how small, could end up causing significant problems for many developers. Far better to be safe than sorry.
The first phase took advantage of out-of-process operation to host extensions that analyze and parse code, working with what can be quite large document trees. That can be memory-intensive, and by running in its own process, an extension can be managed by Windows’ own schedulers, protecting Visual Studio. For example, you could write a linter that loads your current document window contents, parses them, and delivers results without affecting the main Visual Studio process. A lot of code being scanned could have locked your edit window. Instead, the scan now runs in a separate process while you continue to work, staying in flow and in focus.
Phase 2: Adding UIs to extensions
The second phase of the new extensibility model launched recently, taking the out-of-process model much further with support for a remote UI framework. This uses the familiar model-view-viewmodel pattern at the heart of much of modern .NET’s UI tools. If you’ve built a MAUI app or similar, you should find the approach used by Visual Studio extensions much the same. Extension windows can be created inside Visual Studio, placed directly by your code, or placed automatically by Visual Studio.
Windows created by this method are a flexible tool; they can be toggled on and off as needed with an asynchronous connection to Visual Studio. Extension windows are an important part of adding your own tools to Microsoft’s IDE. You can visualize actions or add an uncomplicated way of picking new elements for your code. For example, if you’re writing an extension to quickly generate XAML layouts for desktop applications, you could generate a window that holds a catalog of possible layouts, which can be used as a picker that automatically loads a code scaffolding into your application, ready to be customized.
Adding UI to Visual Studio can be powerful, and simple extension options quickly add up to productivity gains. Some of the Phase 2 options allow you to add tooltips to your extensions while others add progress notifications to long-running external commands. This last option is useful for extensions that integrate Visual Studio into devops workflows, so you can see how an external task or test is running. These progress notifications help when working with asynchronous operations in extensions, ensuring that your users don’t quit actions before they’re completed.
There are some significant differences between this approach and traditional Windows Presentation Foundation development. Perhaps the most important thing to note is that you can’t use your own controls. You can use only Remote UI’s own set. This is to support Visual Studio’s themes, as you don’t want your extension to clash with the rest of the application. Theme support can be added by importing style resources from the Visual Studio shell to style your extension.
Another useful feature in Phase 2 is support for in-process APIs. This allows an extension to work with older APIs when you’re either porting an older extension to the new model or you want to mix older and newer functions in the same code. This can add risk, but it’s a good way to get your extension into the Visual Studio marketplace while you wait for future phases to add APIs and features you need.
Although this isn’t an open-source project, documentation is being developed and delivered on GitHub. Alongside the documentation, Microsoft has delivered a set of project templates and tools for testing and debugging your own extensions through the Visual Studio Marketplace, ready for use. This should give you everything you need to start building your own out-of-process extensions for Visual Studio. The result should be a more stable development platform for everyone.