### Initialize and Get Tool Window Content (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/ToolWindowSample/README.md This C# code shows the asynchronous initialization and content retrieval for a Visual Studio tool window. `InitializeAsync` is used for setup tasks like creating a data context, while `GetContentAsync` provides the `IRemoteUserControl` for the tool window's UI. ```csharp public override Task InitializeAsync(CancellationToken cancellationToken) { this.dataContext = new MyToolWindowData(this.Extensibility); return Task.CompletedTask; } public override Task GetContentAsync(CancellationToken cancellationToken) { return Task.FromResult(new MyToolWindowControl(this.dataContext)); } ``` -------------------------------- ### Upgrade VSIX Project Package References for Dev17 Source: https://github.com/microsoft/vsextensibility/wiki/Samples Updates `Microsoft.VisualStudio.SDK` and `Microsoft.VSSDK.BuildTools` package references to their Dev17 compatible versions. This ensures the project builds against the correct Visual Studio SDK. ```xml ``` -------------------------------- ### Configure VSIX Installation Target for Dev17 Source: https://github.com/microsoft/vsextensibility/wiki/Samples Modifies the `source.extension.vsixmanifest` file to target Visual Studio 2022 (Dev17) and specifies an amd64 payload. This ensures the VSIX is installed in the correct Visual Studio version. ```xml amd64 ``` -------------------------------- ### Show Prompt with Custom Icon and Title Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md Demonstrates how to display a prompt with a custom title and icon. The `ImageMoniker.KnownValues.StatusSecurityWarning` is used as an example icon, and the title is customized using the `with` expression. This allows for more visually informative prompts. ```csharp bool confirmConfiguration = await shell.ShowPromptAsync( $"The selected system ({selectedSystem}) may require additional resources. Do you want to proceed?", PromptOptions.OKCancel with { Title = Title, Icon = ImageMoniker.KnownValues.StatusSecurityWarning, }, cancellationToken); ``` -------------------------------- ### Add Project Reference for Dev17 VSIX Source: https://github.com/microsoft/vsextensibility/wiki/Samples This snippet shows how to add a reference to `System.Windows.Forms` which is required for Dev17 VSIX projects. This is a necessary step when encountering build errors related to missing assemblies. ```xml ``` -------------------------------- ### Update Project References with NuGet Package - XML Source: https://github.com/microsoft/vsextensibility/wiki/Samples This snippet shows how to replace older, specific Visual Studio SDK package references with a single, consolidated NuGet package, Microsoft.VisualStudio.SDK. This simplifies project dependencies and ensures compatibility with newer Visual Studio versions. The change is demonstrated using an XML diff. ```xml - - - 14.0.0-beta4 - - - 15.8.3247 - runtime; build; native; contentfiles; analyzers - all - - + + + 16.9.31025.194 + + ``` -------------------------------- ### Get User Feedback with Default Text Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md This C# snippet demonstrates how to prompt the user for feedback using `shell.ShowPromptAsync` with `InputPromptOptions`. It includes setting default text, an icon, and a title. The function returns the user's input as a nullable string, or null if dismissed. ```csharp string? feedback = await shell.ShowPromptAsync( $"Thank you for configuring {projectName}. Do you have any feedback?", new InputPromptOptions { DefaultText = "Works as expected.", Icon = ImageMoniker.KnownValues.Feedback, Title = Title, }, cancellationToken); ``` -------------------------------- ### Prompt for Project Name with Default Input Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md This C# snippet shows a simpler way to prompt the user for input, like a project name, by utilizing `InputPromptOptions.Default`. It allows for setting a title while using the default empty string as a starting point for user input. The function returns the user's input as a nullable string or null if dismissed. ```csharp string? projectName = await shell.ShowPromptAsync( "Enter the name of the project to configure?", InputPromptOptions.Default with { Title = Title }, cancellationToken); ``` -------------------------------- ### Update VSIX Prerequisite for Dev17 Source: https://github.com/microsoft/vsextensibility/wiki/Samples Adjusts the prerequisite in the `source.extension.vsixmanifest` file to only include Dev17 and above for the core editor. This ensures compatibility with the targeted Visual Studio version. ```xml ``` -------------------------------- ### Create Server Connection for Rust Language Server in C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/RustLanguageServerProvider/README.md This C# code implements the 'CreateServerConnectionAsync' method to establish communication with the rust-analyzer executable. It starts the 'rust-analyzer.exe' process and creates a 'DuplexPipe' to handle standard input and output for communication between Visual Studio and the language server. ```csharp using System.IO; using System.IO.Pipes; using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.Extensibility; using Microsoft.VisualStudio.LanguageServer.Provider; public override Task CreateServerConnectionAsync(CancellationToken cancellationToken) { ProcessStartInfo info = new ProcessStartInfo(); info.FileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, @"rust-analyzer.exe"); info.RedirectStandardInput = true; info.RedirectStandardOutput = true; info.UseShellExecute = false; info.CreateNoWindow = true; Process process = new Process(); process.StartInfo = info; if (process.Start()) { return Task.FromResult(new DuplexPipe( PipeReader.Create(process.StandardOutput.BaseStream), PipeWriter.Create(process.StandardInput.BaseStream))); } return Task.FromResult(null); } ``` -------------------------------- ### Get ShellExtensibility Helpers Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md Retrieves the ShellExtensibility helpers object from the Extensibility object within a Visual Studio extension's command handler. This object provides access to various shell-related functionalities, including user prompts. ```csharp var shell = this.Extensibility.Shell(); ``` -------------------------------- ### Show Prompt with Custom Options Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md Presents a prompt to the user with a set of custom choices defined using `PromptOptions`. The user's selection is mapped to a specific enum value (`TokenThemeResult` in this example). It also demonstrates setting a default selection and a return value for when the prompt is dismissed. ```csharp // Custom prompt var themeResult = await shell.ShowPromptAsync( "Which theme should be used for the generated output?", new PromptOptions { Choices = { { "Solarized Is Awesome", TokenThemeResult.Solarized }, { "OneDark Is The Best", TokenThemeResult.OneDark }, { "GruvBox Is Groovy", TokenThemeResult.GruvBox }, }, DismissedReturns = TokenThemeResult.None, DefaultChoiceIndex = 2, }, ct); ``` -------------------------------- ### Load/Unload Project from Solution (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md Provides code examples for unloading and reloading a specific project from a solution. It uses the UpdateSolutionAsync API to target a solution by its base name and then applies either UnloadProject or ReloadProject to the specified project path. Requires the solution name and project path as input. ```csharp await this.Extensibility.Workspaces().UpdateSolutionAsync( solution => solution.Where(solution => solution.BaseName == solutionName), solution => solution.UnloadProject(projectPath), cancellationToken); await this.Extensibility.Workspaces().UpdateSolutionAsync( solution => solution.Where(solution => solution.BaseName == solutionName), solution => solution.ReloadProject(projectPath), cancellationToken); ``` -------------------------------- ### Move File by Copying and Deleting in C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md This example provides a workaround for moving files as a direct `MoveFile` API is not available. It first copies the file to the destination and then deletes the original. This ensures data integrity during the file transfer process across projects. ```csharp var result = await this.Extensibility.Workspaces().UpdateProjectsAsync( project => project.Where(project => project.Name == "ConsoleApp2"), project => project.AddFileFromCopy(sourceFilePath, destinationProject), cancellationToken); ``` ```csharp await sourceFile.AsUpdatable().Delete().ExecuteAsync(); ``` -------------------------------- ### Update csproj for Shared Project Dependencies (XML) Source: https://github.com/microsoft/vsextensibility/wiki/Samples This snippet demonstrates how to modify a .csproj file to correctly link and compile source files from a shared project, particularly when a VSCT file depends on a C# file. It shows the transformation from standard Content/Compile includes to VSCTCompile and updated Compile elements with dependency declarations. ```xml - - ImageOptimizer.vsct - - - ImageOptimizer.cs - + + Menus.ctmenu + VsctGenerator + ..\SharedFiles\ImageOptimizer.cs + + + True + True + ..\SharedFiles\ImageOptimizer.vsct + ``` -------------------------------- ### C# LSP Extensions: Diagnostics and Project Context Source: https://context7.com/microsoft/vsextensibility/llms.txt This snippet demonstrates how to configure JsonSerializer for VS extensions, declare server capabilities for project context provider, and format VSDiagnostic objects with enhanced properties like tooltips and project information. It also includes examples of GetProjectContexts requests and responses, showcasing how language servers can query project details for multi-targeting scenarios. Requires Microsoft.VisualStudio.LanguageServer.Protocol and Microsoft.VisualStudio.LanguageServer.Protocol.Extensions NuGet packages. ```csharp // Example NuGet package references in .csproj // // // // // Configure JsonSerializer to support VS extensions // VSExtensionUtilities.AddVSExtensionConverters(jsonSerializer); // Server capabilities declaration { "capabilities": { "_vs_projectContextProvider": true } } // VSDiagnostic example with enhanced properties { "range": { "start": {"line": 10, "character": 5}, "end": {"line": 10, "character": 15} }, "severity": 1, "code": "CS1001", "message": "Identifier expected", "_vs_toolTip": "An identifier is required in this context. Check for missing variable or method names.", "_vs_diagnosticRank": 200, "_vs_diagnosticType": "Syntax", "_vs_projects": [ { "_vs_projectName": "MyProject", "_vs_context": "Debug|AnyCPU", "_vs_projectIdentifier": "12345678-1234-1234-1234-123456789012" } ] } // GetProjectContexts request { "jsonrpc": "2.0", "id": 1, "method": "textDocument/_vs_getProjectContexts", "params": { "_vs_textDocument": { "uri": "file:///path/to/file.cs", "languageId": "csharp", "version": 1, "text": "..." } } } // GetProjectContexts response { "jsonrpc": "2.0", "id": 1, "result": { "_vs_projectContexts": [ { "_vs_label": "net8.0", "_vs_id": "net8.0", "_vs_kind": 2 }, { "_vs_label": "net48", "_vs_id": "net48", "_vs_kind": 2 } ], "_vs_defaultIndex": 0 } } ``` -------------------------------- ### Set Startup Projects (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md Demonstrates how to set one or more projects as the startup projects for a solution. It uses the UpdateSolutionAsync API to select a solution by its base name and then calls SetStartupProjects with the paths of the desired startup projects. Requires solution name and project paths. ```csharp await this.Extensibility.Workspaces().UpdateSolutionAsync( solution => solution.Where(solution => solution.BaseName == solutionName), solution => solution.SetStartupProjects(projectPath1, projectPath2), cancellationToken); ``` -------------------------------- ### Get Active Text View in C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/InsertGuid/README.md Retrieves the currently active text view in the Visual Studio IDE. This allows access to document information and user selections for subsequent editor manipulation. It requires an IClientContext and cancellation token. ```csharp using var textView = await context.GetActiveTextViewAsync(cancellationToken); ``` -------------------------------- ### Setting ID Validation Example in C# Source: https://github.com/microsoft/vsextensibility/blob/main/docs/breaking_changes.md Demonstrates valid and invalid setting identifiers for VisualStudio.Extensibility extensions. It highlights the requirement for setting IDs to start with a lowercase letter and not contain special characters. This change aims to improve the robustness of extension settings management. ```csharp public static SettingCategory MySettingCategory => new("settingsSample", "Settings Sample") public static SettingCategory MySettingCategory => new("SettingsSample", "Settings Sample") public static SettingCategory MySettingCategory => new("0SettingsSample", "Settings Sample") public static SettingCategory MySettingCategory => new("a", "Settings Sample") ``` -------------------------------- ### Extension Entry Point with VisualStudioContribution Source: https://context7.com/microsoft/vsextensibility/llms.txt Defines the entry point for a Visual Studio extension, inheriting from 'Extension' and decorated with '[VisualStudioContribution]'. This class configures extension metadata such as ID, version, publisher, display name, and description. It also allows for optional service initialization via dependency injection. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.VisualStudio.Extensibility; [VisualStudioContribution] public class InsertGuidExtension : Extension { public override ExtensionConfiguration ExtensionConfiguration => new() { Metadata = new( id: "InsertGuid.c5481000-68da-416d-b337-32122a638980", version: this.ExtensionAssemblyVersion, publisherName: "Microsoft", displayName: "Insert Guid Sample Extension", description: "Sample extension demonstrating inserting text in the current document"), }; protected override void InitializeServices(IServiceCollection serviceCollection) { base.InitializeServices(serviceCollection); // Register additional services here } } ``` -------------------------------- ### Define Insert Guid Command in C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/InsertGuid/README.md Defines a Visual Studio command that inserts a GUID. It uses the VisualStudioContribution attribute for registration and CommandConfiguration for properties like placement and icon. The command is visible when an active editor is present. ```csharp [VisualStudioContribution] internal class InsertGuidCommand : Command { public override CommandConfiguration CommandConfiguration => new("%InsertGuid.InsertGuidCommand.DisplayName%") { Placements = [CommandPlacement.KnownPlacements.ExtensionsMenu], Icon = new(ImageMoniker.KnownValues.OfficeWebExtension, IconSettings.IconAndText), VisibleWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveEditorContentType, ".+"), }; } ``` -------------------------------- ### Declare Multiple VS Installation Targets in VSIX Manifest Source: https://github.com/microsoft/vsextensibility/wiki/No-Code-Extensions This XML snippet demonstrates how to declare two installation targets within the `` element of a `source.extension.vsixmanifest` file. It specifies support for both Visual Studio 2017 (versions 15.0 to 17.0) with x86 architecture and Visual Studio 2022 (versions 17.0 to 18.0) with amd64 architecture. This allows a single VSIX to be compatible with multiple VS versions. ```xml x86 amd64 ``` -------------------------------- ### Mutate Text in Active View using C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/InsertGuid/README.md Edits the text within the active editor view by replacing the current selection with a new GUID string. This operation is performed within an edit batch for atomic updates and requires the document and selection extent from the active text view. ```csharp var document = await textView.GetTextDocumentAsync(cancellationToken); await this.Extensibility.Editor().EditAsync( batch => { document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString); }, cancellationToken); ``` -------------------------------- ### Configure VSIX Manifest for Dev17 Installation Target Source: https://github.com/microsoft/vsextensibility/wiki/Add-Dev17-Target This XML snippet illustrates how to configure the `source.extension.vsixmanifest` file to target Dev17. It specifically shows the `InstallationTarget` element with the `Id` set to `Microsoft.VisualStudio.Community` and a `Version` range. Crucially, it includes the `ProductArchitecture` element set to `amd64`, which is mandatory for Dev17 installations. ```xml amd64 ``` -------------------------------- ### Define Command with VisualStudioContribution Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md Defines a command for Visual Studio extensions using the VisualStudioContribution attribute. This attribute registers the command with Visual Studio, making it available for execution. The command's properties, such as display name and tooltip, are configured via the CommandConfiguration. ```csharp [VisualStudioContribution] internal class SampleCommand : Command { } ``` ```csharp public override CommandConfiguration CommandConfiguration => new("%UserPromptSample.SampleCommand.DisplayName%") { TooltipText = "%UserPromptSample.SampleCommand.ToolTip%", Placements = [CommandPlacement.KnownPlacements.ToolsMenu], }; ``` -------------------------------- ### Get Custom Code Lens Visualization (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/CodeLensSample/README.md Provides a custom UI visualization for the Code Lens, represented by `WordCountCodeLensVisual`, which is associated with the word count data. ```csharp public override Task GetVisualizationAsync(CodeElementContext codeElementContext, IClientContext clientContext, CancellationToken token) { return Task.FromResult(new WordCountCodeLensVisual(this.wordCountData)); } ``` -------------------------------- ### Project Configuration Source: https://context7.com/microsoft/vsextensibility/llms.txt Define extension dependencies and build settings for Visual Studio extensions. ```APIDOC ## Project Configuration ### Description Define extension dependencies and build settings. ### .csproj Example This example shows a typical `.csproj` file for a Visual Studio extension, targeting .NET 8.0 with Windows support and including necessary SDK packages. ```xml net8.0-windows8.0 enable 12 en-US True True Resources.resx ResXFileCodeGenerator Resources.Designer.cs ``` ### Dependencies - **Microsoft.VisualStudio.Extensibility.Sdk**: Core SDK for building Visual Studio extensions. - **Microsoft.VisualStudio.Extensibility.Build**: Build tools for packaging and deploying extensions. ### Resource Files Resource files (`.resx`) are used for localized strings and can support multiple languages through satellite assemblies. ``` -------------------------------- ### Create Tool Window in C# Source: https://context7.com/microsoft/vsextensibility/llms.txt Demonstrates how to create a dockable tool window within the Visual Studio IDE. This involves defining a command to trigger the window's display and a separate class for the tool window's UI. The tool window persists across sessions and can be repositioned by the user. ```csharp using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.Extensibility; using Microsoft.VisualStudio.Extensibility.Commands; [VisualStudioContribution] public class MyToolWindowCommand : Command { public override CommandConfiguration CommandConfiguration => new("%ToolWindowSample.MyToolWindowCommand.DisplayName%") { Placements = [CommandPlacement.KnownPlacements.ToolsMenu], Icon = new(ImageMoniker.KnownValues.ToolWindow, IconSettings.IconAndText), }; public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) { await this.Extensibility.Shell().ShowToolWindowAsync(activate: true, cancellationToken); } } ``` -------------------------------- ### Display User Prompts in C# Source: https://context7.com/microsoft/vsextensibility/llms.txt Illustrates how to display simple prompts and confirmation dialogs to users using the Visual Studio extensibility shell. This includes showing basic confirmations, prompts with customizable default options, and custom choice prompts with type-safe enum results. These are ideal for user confirmations, warnings, and simple decision points. ```csharp using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.Extensibility; using Microsoft.VisualStudio.Extensibility.Commands; using Microsoft.VisualStudio.Extensibility.Shell; [VisualStudioContribution] public class SampleCommand : Command { public enum TokenThemeResult { None, Solarized, OneDark, GruvBox, } public override CommandConfiguration CommandConfiguration => new("Sample Command") { Placements = [CommandPlacement.KnownPlacements.ToolsMenu], }; public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken ct) { var shell = this.Extensibility.Shell(); // Simple confirmation if (!await shell.ShowPromptAsync("Continue with executing the command?", PromptOptions.OKCancel, ct)) { return; } // Confirmation with Cancel as default (for dangerous operations) if (!await shell.ShowPromptAsync("Delete all files?", PromptOptions.OKCancel.WithCancelAsDefault(), ct)) { return; } // Information-only prompt await shell.ShowPromptAsync("The extension must reload.", PromptOptions.OK, ct); // Custom choices with type-safe enum result var themeResult = await shell.ShowPromptAsync( "Which theme should be used?", new PromptOptions { Choices = { { "Solarized Is Awesome", TokenThemeResult.Solarized }, { "OneDark Is The Best", TokenThemeResult.OneDark }, { "GruvBox Is Groovy", TokenThemeResult.GruvBox }, }, DismissedReturns = TokenThemeResult.None, DefaultChoiceIndex = 2, }, ct); } } ``` -------------------------------- ### GetProjectContexts Source: https://github.com/microsoft/vsextensibility/blob/main/docs/lsp/lsp-extensions-specifications.md Requests are sent from the client to the server to retrieve a list of the project contexts associated with a text document. An example of project contexts are multiple target frameworks in SDK style .NET projects. ```APIDOC ## textDocument/_vs_getProjectContexts ### Description Requests are sent from the client to the server to retrieve a list of the project contexts associated with a text document. An example of project contexts are multiple target frameworks in SDK style .NET projects. ### Method POST ### Endpoint textDocument/_vs_getProjectContexts ### Parameters #### Query Parameters - **_vs_projectContextProvider** (boolean) - Optional - Indicates if the server supports project contexts. #### Request Body - **textDocument** (VSTextDocumentIdentifier) - Required - The text document for which to retrieve project contexts. - **uri** (string) - The URI of the text document. - **_vs_projectContext** (VSProjectContext) - Optional - The currently active project context. - **id** (string) - The ID of the project context. - **label** (string) - The label of the project context. ### Request Example ```json { "textDocument": { "uri": "file:///path/to/document.cs", "_vs_projectContext": { "id": "project-id-123", "label": "net6.0" } } } ``` ### Response #### Success Response (200) - **items** (array of VSProjectContext) - A list of project contexts associated with the text document. - **id** (string) - The ID of the project context. - **label** (string) - The label of the project context. #### Response Example ```json { "items": [ { "id": "project-id-123", "label": "net6.0" }, { "id": "project-id-456", "label": "net7.0" } ] } ``` ``` -------------------------------- ### Prompt User to Select Folder Dialog (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/FilePickerSample/README.md Demonstrates selecting a folder using `ShowOpenFolderDialogAsync`. Requires a `FolderDialogOptions` object for configuration. Returns the selected folder path or null if canceled. ```csharp FolderDialogOptions options = new(); string? folderPath = await this.Extensibility.Shell().ShowOpenFolderDialogAsync(options, ct); ``` -------------------------------- ### Define VSImageId Interface (TypeScript) Source: https://github.com/microsoft/vsextensibility/blob/main/docs/lsp/lsp-extensions-specifications.md Defines the VSImageId interface, which represents a unique identifier for a Visual Studio image asset. It consists of a GUID and an integer. Valid image IDs can be found in the KnownMonikers class. ```typescript export interface VSImageId { /** * Gets or sets the VSImageId._vs_guid component of the unique identifier. **/ _vs_guid : Guid, /** * Gets or sets the integer component of the unique identifier. **/ _vs_id : integer, } ``` -------------------------------- ### Get Code Lens Label with Word Count (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/CodeLensSample/README.md Calculates the word count for a given code element's range and returns a `CodeLensLabel` object. The label displays the word count and a tooltip. ```csharp public override Task GetLabelAsync(CodeElementContext codeElementContext, CancellationToken token) { this.wordCountData.WordCount = CountWords(codeElementContext.Range); return Task.FromResult(new CodeLensLabel() { Text = $"Words: {this.wordCountData.WordCount}", Tooltip = "Number of words in this code element", }); } ``` -------------------------------- ### Define Rust Language Server Provider in C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/RustLanguageServerProvider/README.md This C# code defines a class 'RustLanguageServerProvider' that inherits from 'LanguageServerProvider'. The '[VisualStudioContribution]' attribute registers this class as a language server provider with Visual Studio. It sets up the basic structure for a language server extension. ```csharp using Microsoft.VisualStudio.Extensibility; using Microsoft.VisualStudio.LanguageServer.Provider; namespace RustLspExtension { [VisualStudioContribution] internal class RustLanguageServerProvider : LanguageServerProvider { } } ``` -------------------------------- ### Get Label for Clickable Code Lens Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/CodeLensSample/README.md Retrieves the label text and tooltip for the clickable Code Lens. The text dynamically updates to show the number of times the lens has been clicked, defaulting to 'Click me' if not clicked yet. ```csharp public override Task GetLabelAsync(CodeElementContext codeElementContext, CancellationToken token) { return Task.FromResult(new CodeLensLabel() { Text = this.clickCount == 0 ? "Click me" : $"Clicked {this.clickCount} times", Tooltip = "Invokable CodeLens Sample Tooltip", }); } ``` -------------------------------- ### Update VSIX Manifest Installation Target for VS 2019 Source: https://github.com/microsoft/vsextensibility/wiki/Downtargeting-To-VS2019 Modifies the `InstallationTarget` in the `source.extension.vsixmanifest` file to specify the version range for Visual Studio 2019. This ensures the extension is compatible with the targeted VS version. ```diff - + - amd64 ``` -------------------------------- ### Invoke Solution Build Actions (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md Demonstrates how to invoke build actions such as BuildAsync, RebuildAsync, and CleanAsync on a solution level. It queries for all solutions and then iterates through each one to perform the specified build action. Requires access to the Extensibility.Workspaces API. ```csharp IQueryResults solutions = await this.Extensibility.Workspaces().QuerySolutionAsync(s => s, cancellationToken); foreach (var solution in solutions) { await solution.AsQueryable().BuildAsync(cancellationToken); } ``` -------------------------------- ### Example JSON for String Localization Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/CommentRemover/README.md This JSON object defines localizable strings for a Visual Studio extension. Keys represent string identifiers, and values are the default English strings. These can be expanded with language-specific resource files for localization. ```json { "CommentRemover.CommentRemoverMenu.DisplayName": "Comments", "CommentRemover.RemoveAllComments.DisplayName": "Remove All", "CommentRemover.RemoveAllExceptTaskComments.DisplayName": "Remove All Except Tasks", "CommentRemover.RemoveAllExceptXmlDocComments.DisplayName": "Remove All Except Xml Docs", "CommentRemover.RemoveRegions.DisplayName": "Remove Regions", "CommentRemover.RemoveTasks.DisplayName": "Remove Tasks", "CommentRemover.RemoveXmlDocComments.DisplayName": "Remove Xml Docs" } ``` -------------------------------- ### Implement File and Folder Picker Dialogs in C# Source: https://context7.com/microsoft/vsextensibility/llms.txt Allows extensions to prompt users for file or folder selection using native dialogs. Supports customizable filters, default filenames, and multi-selection. Returns file paths or null if canceled. Depends on Microsoft.VisualStudio.Extensibility.Shell.FileDialog. ```csharp using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.Extensibility; using Microsoft.VisualStudio.Extensibility.Commands; using Microsoft.VisualStudio.Extensibility.Shell.FileDialog; [VisualStudioContribution] public class OpenFileCommand : Command { public override CommandConfiguration CommandConfiguration => new("%FilePickerSample.OpenFileCommand.DisplayName%") { Placements = [CommandPlacement.KnownPlacements.ToolsMenu], Icon = new(ImageMoniker.KnownValues.OpenFileDialog, IconSettings.IconAndText), }; public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken ct) { // Single file selection FileDialogOptions options = new() { InitialFileName = "test.cs", Filters = new DialogFilters([ new("Log Files", "*.txt", "*.log"), new("CSharp Files", "*.cs"), ]) { DefaultFilterIndex = 1, }, }; string? filePath = await this.Extensibility.Shell().ShowOpenFileDialogAsync(options, ct); // Multiple file selection IReadOnlyList? filePaths = await this.Extensibility.Shell().ShowOpenMultipleFilesDialogAsync(options, ct); // Save as dialog FileDialogOptions saveOptions = new() { Title = "Save as File", InitialFileName = "result.txt", }; string? savePath = await this.Extensibility.Shell().ShowSaveAsFileDialogAsync(saveOptions, ct); // Folder selection FolderDialogOptions folderOptions = new(); string? folderPath = await this.Extensibility.Shell().ShowOpenFolderDialogAsync(folderOptions, ct); } } ``` -------------------------------- ### Obsolete Project Query Methods in VisualStudio.Extensibility Source: https://github.com/microsoft/vsextensibility/blob/main/docs/breaking_changes.md These methods within Microsoft.VisualStudio.ProjectSystem.Query have been marked as Obsolete and are scheduled for future removal. Developers should avoid using these methods and consider alternative approaches if they are currently in use. No direct code example is provided as these are method signatures being marked. ```csharp Microsoft.VisualStudio.ProjectSystem.Query.UpdateExtensions.SetBuildPropertyValue(this IAsyncUpdatable configurations, string name, string value, string storageType) Microsoft.VisualStudio.ProjectSystem.Query.UpdateExtensions.Delete(this IAsyncUpdatable buildProperties) Microsoft.VisualStudio.ProjectSystem.Query.ProjectConfigurationPropertiesFilterExtensions.BuildPropertiesByName(this IProjectConfigurationSnapshot projectConfiguration, string storageType, params string[] buildPropertyNames) ``` -------------------------------- ### Configure Container Project for WPF Controls (XML) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/ExtensionWithTraditionalComponents/README.md These XML settings for the Container.csproj enable WPF user control integration. 'GeneratePkgDefFile' ensures a .pkgdef file is created, 'UseCodebase' uses codebases for pkgdef generation, 'SignAssembly' enables strong-naming, and 'AssemblyOriginatorKeyFile' specifies the key file for signing. Strong-named assemblies are required for Visual Studio to load them. ```xml true true True sgKey.snk ``` -------------------------------- ### Establish Queryable Space with Project System Query Service Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectQueryAPIBrowser.md This C# code snippet demonstrates how to obtain an instance of the IProjectSystemQueryService and establish an IProjectModelQueryableSpace. This is the initial step required to interact with the Project System's query capabilities. ```csharp var service = (IProjectSystemQueryService)await ServiceProvider.GetGlobalServiceAsync(typeof(IProjectSystemQueryService)); IProjectModelQueryableSpace queryableSpace = await service.GetProjectModelQueryableSpaceAsync(); ``` -------------------------------- ### Configure Rust Language Server Display Name in JSON Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/RustLanguageServerProvider/README.md This JSON snippet defines the localized display name for the Rust Language Server Provider. It maps the resource key '%RustLspExtension.RustLanguageServerProvider.DisplayName%' to the user-facing string 'Rust Analyzer LSP server', which will be shown in Visual Studio. ```json { "RustLspExtension.RustLanguageServerProvider.DisplayName": "Rust Analyzer LSP server" } ``` -------------------------------- ### Get Editor Option Values (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/docs/breaking_changes.md Demonstrates two patterns for obtaining editor option values using `ITextViewSnapshot.GetOptionValueAsync()`. The first pattern is shown as potentially throwing an exception, while the second uses `ValueOrDefault` to safely retrieve the value with a default, preventing exceptions. This requires the `Microsoft.VisualStudio.Extensibility.Editor` package. ```csharp // Potentially throws bool useSpaces = (await textView.GetOptionValueAsync(KnownDocumentOptions.ConvertTabsToSpacesOption, cancellationToken)).Value; ``` ```csharp // Never throws bool useSpaces = (await textView.GetOptionValueAsync(KnownDocumentOptions.ConvertTabsToSpacesOption, cancellationToken)).ValueOrDefault(defaultValue: false); ``` -------------------------------- ### Prompt User to Open Multiple Files Dialog (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/FilePickerSample/README.md Shows how to allow the user to select multiple files using `ShowOpenMultipleFilesDialogAsync`. The `FileDialogOptions` can configure filters. Returns a list of selected file paths or null if canceled. ```csharp FileDialogOptions options = new() { InitialFileName = "test.cs", Filters = new DialogFilters( new("Log Files", "*.txt", "*.log"), new("CSharp Files", "*.cs")), }; IReadOnlyList? filePaths = await this.Extensibility.Shell().ShowOpenMultipleFilesDialogAsync(options, ct); ``` -------------------------------- ### Get Active TextView in Visual Studio Extension using C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/EncodeDecodeBase64/README.md This C# code demonstrates how to retrieve the active text view within a Visual Studio extension context. It utilizes the `context.GetActiveTextViewAsync` method to obtain an `ITextViewSnapshot` object, which provides information about the currently open document and its state. ```csharp using var textView = await context.GetActiveTextViewAsync(cancellationToken); ``` -------------------------------- ### Show Confirmation Prompt with OKCancel Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/UserPromptSample/README.md Displays a standard confirmation prompt to the user with 'OK' and 'Cancel' options using the ShowPromptAsync method. The method returns a boolean indicating whether the user confirmed the operation. If the user cancels, the method returns false, and the command handler can exit early. ```csharp if (!await shell.ShowPromptAsync("Continue with executing the command?", PromptOptions.OKCancel, ct)) { return; } ``` -------------------------------- ### Define Tool Window Command - C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/ToolWindowSample/README.md Defines a command that shows a specific tool window. It uses the `VisualStudioContribution` attribute to make the command available to Visual Studio and specifies placement, icon, and execution logic. The `ShowToolWindowAsync` method is used to display the tool window, with an option to activate (focus) it. ```csharp [VisualStudioContribution] public class MyToolWindowCommand : Command { public override CommandConfiguration CommandConfiguration => new("%ToolWindowSample.MyToolWindowCommand.DisplayName%") { Placements = [CommandPlacement.KnownPlacements.ToolsMenu], Icon = new(ImageMoniker.KnownValues.ToolWindow, IconSettings.IconAndText) }; public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) { await this.Extensibility.Shell().ShowToolWindowAsync(activate: true, cancellationToken); } } ``` -------------------------------- ### Define a Visual Studio Command Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/DialogSample/README.md Defines a Visual Studio command using the `VisualStudioContribution` attribute. The `CommandConfiguration` property specifies command properties like display name, menu placement, and icon. The `ExecuteCommandAsync` method handles the command's execution logic, in this case, showing a dialog. ```csharp using Microsoft.VisualStudio.Extensibility; using Microsoft.VisualStudio.Extensibility.Commands; using Microsoft.VisualStudio.Extensibility.Framework; using Microsoft.VisualStudio.Extensibility.Framework.Shell; using Microsoft.VisualStudio.Extensibility.Utilities; using System; using System.Threading; using System.Threading.Tasks; [VisualStudioContribution] public class MyDialogCommand : Command { public override CommandConfiguration CommandConfiguration => new("%DialogSample.MyDialogCommand.DisplayName%") { Placements = [CommandPlacement.KnownPlacements.ToolsMenu], Icon = new(ImageMoniker.KnownValues.Dialog, IconSettings.IconAndText), }; public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) { // Ownership of the RemoteUserControl is transferred to VisualStudio, so it should not be disposed by the extension #pragma warning disable CA2000 // Dispose objects before losing scope var control = new MyDialogControl(null); #pragma warning restore CA2000 // Dispose objects before losing scope await this.Extensibility.Shell().ShowDialogAsync(control, cancellationToken); } } ``` -------------------------------- ### Define Command with VisualStudioContribution Attribute - C# Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/SimpleRemoteCommandSample/README.md This C# code snippet defines a command handler for Visual Studio extensions. The `VisualStudioContribution` attribute registers the command, making it available in Visual Studio. The `CommandConfiguration` property specifies details like placement and icon. ```csharp [VisualStudioContribution] internal class CommandHandler : Command { public override CommandConfiguration CommandConfiguration => new("%SimpleRemoteCommandSample.CommandHandler.DisplayName%") { Placements = [CommandPlacement.KnownPlacements.ToolsMenu], Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText) }; } ``` -------------------------------- ### Manage Solution Configurations (C#) Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md Illustrates how to add and delete solution configurations. AddSolutionConfiguration takes the new configuration name, the base configuration name, and a boolean for propagation. DeleteSolutionConfiguration removes an existing configuration by name. Both use UpdateSolutionAsync. ```csharp await this.Extensibility.Workspaces().UpdateSolutionAsync( solution => solution.Where(solution => solution.BaseName == solutionName), solution => solution.AddSolutionConfiguration("Foo", "Debug", false), cancellationToken); await this.Extensibility.Workspaces().UpdateSolutionAsync( solution => solution.Where(solution => solution.BaseName == solutionName), solution => solution.DeleteSolutionConfiguration("Foo"), cancellationToken); ``` -------------------------------- ### Retrieve Project Information using Project Query API Source: https://github.com/microsoft/vsextensibility/blob/main/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectQueryAPIBrowser.md This C# code demonstrates a query to retrieve detailed information about projects, including their names, paths, GUIDs, and file-related properties (ItemType, ItemName, Path, LinkPath, VisualPath). It utilizes the With() method to specify the desired data and ExecuteQueryAsync() to run the query. ```csharp var result = await queryableSpace.Projects .With(project => project.Name) .With(project => project.Path) .With(project => project.Files .With(file => file.ItemType) .With(file => file.ItemName) .With(file => file.Path) .With(file => file.LinkPath) .With(file => file.VisualPath)) .With(project => project.Guid) .ExecuteQueryAsync(); ```