From dedaf0ab3e123ad9dc746ff5e6e239ddf9a6d46b Mon Sep 17 00:00:00 2001 From: Jasmine Woon Date: Wed, 17 Jan 2024 08:08:33 -0800 Subject: [PATCH] Update readme and commands --- .../AddSolutionConfigurationCommand.cs | 38 +++++++ .../DeleteSolutionConfigurationCommand.cs | 38 +++++++ .../ProjectBuildCommand.cs | 37 +++++++ .../ProjectQueryAPIBrowser.md | 2 +- .../QuerySolutionConfigurations.cs | 48 ++++++++ .../Samples/VSProjectQueryAPISample/README.md | 104 +++++++++++++++++- .../ReloadProjectCommand.cs | 37 +++++++ .../RenameProjectCommand.cs | 37 +++++++ .../SetStartupProjectsCommand.cs | 38 +++++++ .../SolutionBuildCommand.cs | 34 ++++++ .../SolutionSaveCommand.cs | 33 ++++++ .../UnloadProjectCommand.cs | 37 +++++++ 12 files changed, 480 insertions(+), 3 deletions(-) create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/AddSolutionConfigurationCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/DeleteSolutionConfigurationCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectBuildCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/QuerySolutionConfigurations.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/ReloadProjectCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/RenameProjectCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/SetStartupProjectsCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionBuildCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionSaveCommand.cs create mode 100644 New_Extensibility_Model/Samples/VSProjectQueryAPISample/UnloadProjectCommand.cs diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/AddSolutionConfigurationCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/AddSolutionConfigurationCommand.cs new file mode 100644 index 00000000..3ea24b9e --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/AddSolutionConfigurationCommand.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using System.Globalization; +using System.Text; +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command adding solution configurations. +/// +[VisualStudioContribution] +public class AddSolutionConfigurationCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.AddSolutionConfigurationCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + const string solutionName = "ConsoleApp32"; + + await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.AddSolutionConfiguration("Foo", "Debug", false), + cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Adding solution configuration called 'Foo'.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/DeleteSolutionConfigurationCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/DeleteSolutionConfigurationCommand.cs new file mode 100644 index 00000000..bdd3aa8a --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/DeleteSolutionConfigurationCommand.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using System.Globalization; +using System.Text; +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command deleting a solution configurations. +/// +[VisualStudioContribution] +public class DeleteSolutionConfigurationCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.DeleteSolutionConfigurationCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + const string solutionName = "ConsoleApp32"; + + await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.DeleteSolutionConfiguration("Foo"), + cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Deleting a solution configuration called 'Foo'.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectBuildCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectBuildCommand.cs new file mode 100644 index 00000000..e8ee9c6d --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectBuildCommand.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for building a project. +/// +[VisualStudioContribution] +public class ProjectBuildCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.ProjectBuildCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + const string projectName = "ConsoleApp1"; + + var result = await this.Extensibility.Workspaces().QueryProjectsAsync( + project => project.Where(p => p.Name == projectName), + cancellationToken); + + await result.First().BuildAsync(cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Building project {projectName}.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectQueryAPIBrowser.md b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectQueryAPIBrowser.md index 38e2f6e9..1e794ab5 100644 --- a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectQueryAPIBrowser.md +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ProjectQueryAPIBrowser.md @@ -59,7 +59,7 @@ In our example, we call the `ExecuteQueryAsync` method to get information from t Instead of writing queries, users may use the API Metadata tree located on the left panel of the Project Query API Browser. Users may select/deselect the information that they would like to receive from the query. As users select and deselect items in the tree view, the editor will dynamically change its query. -![APIMetadata](Images/TemplateQueries.png) +![APIMetadata](Images/APIMetaData.png) *Figure 3: Tree View of API Metadata* ## Template Queries diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/QuerySolutionConfigurations.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/QuerySolutionConfigurations.cs new file mode 100644 index 00000000..94c44fbe --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/QuerySolutionConfigurations.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using System.Globalization; +using System.Text; +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for querying solution configurations. +/// +[VisualStudioContribution] +public class QuerySolutionConfigurations : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.QuerySolutionConfigurations.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + var results = await this.Extensibility.Workspaces().QuerySolutionAsync( + solution => solution.With(solution => solution.SolutionConfigurations + .With(c => c.Name)), + cancellationToken); + + StringBuilder message = new StringBuilder(); + + message.Append($"\n \n === Querying Solution Configurations === \n"); + + foreach (var solution in results) + { + foreach (var solutionConfiguration in solution.SolutionConfigurations) + { + message.Append(CultureInfo.CurrentCulture, $"\t \t {solutionConfiguration.Name}\n"); + } + } + + await this.Extensibility.Shell().ShowPromptAsync(message.ToString(), PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md index 27a13e31..ad980c6d 100644 --- a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/README.md @@ -1,7 +1,7 @@ --- title: VS Project Query API Extension reference description: A reference for VS Project Query API Extension reference -date: 2022-1-20 +date: 2024-1-11 --- # Walkthrough: VS Project Query API Extension @@ -89,7 +89,7 @@ var result = await this.Extensibility.Workspaces().QueryProjectsAsync( ### Querying By Id -As usuages for project query becomes more complex, you may realize that the require more information from their query. +As usages for project query becomes more complex, you may realize that the require more information from their query. In our example, let's say we already queried information about Output Groups. @@ -123,3 +123,103 @@ await foreach (var project in result) ``` Now `newResult` will contain information about OutputGroups' names. + +## Sample Queries + +Below is a showcase of queries that are available in the Project Query API + +### Solution Level Queries + +### Solution Build Actions + +In project query, you also have the ability to invoke build actions on the solution level. These build actions include: `BuildAsync`, `RebuildAsync`, `CleanAsync`, `DebugLaunchAsync`, and `LaunchAsync`. + +```csharp +var result = await querySpace.Solutions + .BuildAsync(cancellationToken); +``` + +### Loading/Unloading a Project + +In the snippet below, we specify the solution we would like to unload the project from and pass in the project path when we make our `UnloadProject` call. + +```csharp +await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.UnloadProject(projectPath), + cancellationToken); +``` + +Similarly, we can load the project by calling the `ReloadProject` API. + +```csharp +await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.ReloadProject(projectPath), + cancellationToken); +``` + + +### Saving a Solution + +`SaveAsync` is an API call that can be used on the solution level. + +```csharp +var result = await querySpace.Solutions.SaveAsync(cancellationToken); +``` + + +### Actions for Startup Projects + +Using the Project Query API, you also can select which projects get executed. In the sample below, we added two project paths to be set as the startup project. + +```csharp +await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.SetStartupProjects(projectPath1, projectPath2), + cancellationToken); +``` + +### Actions for Solution Configurations + +`AddSolutionConfiguration` is an API call that takes in three parameters. The first parameter is the new name we want to give our new solution configuration. In this scenario, we will call our new solution configuration `Foo`. The next parameter is the configuration to base our new configuration. Below, we based our new solution configuration on the existing solution configuration, `Debug`. Lastly, the boolean represents if the solution configuration should be propagated. + +```csharp +await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.AddSolutionConfiguration("Foo", "Debug", false), + cancellationToken); +``` + +`DeleteSolutionConfiguration` is an API call that removes the solution configuration. In the example below, we removed the solution configuration called `Foo`. + +```csharp +await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.DeleteSolutionConfiguration("Foo"), + cancellationToken); +``` + + +### Project Level Queries + +### Project Build Actions + +On the project level, you many invoke these build actions: `BuildAsync`, `RebuildAsync`, `CleanAsync`, `DebugLaunchAsync`, and `LaunchAsync`. +While building on the project level, determine the selected project you want to build. In the example below, `result.First()` is an `IProjectSnapshot` that will be built. + +```csharp +await result.First().BuildAsync(cancellationToken); +``` + +### Rename Project + +In the example below, we specify the name of the project we would like to update. We then call `Rename` while passing in the new name of the project. + +```csharp +var result = await querySpace.Projects + .Where(p => p.Name == "ConsoleApp1") + .AsUpdatable() + .Rename("NewProjectName") + .ExecuteAsync(cancellationToken); +``` \ No newline at end of file diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ReloadProjectCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ReloadProjectCommand.cs new file mode 100644 index 00000000..4fe4eb73 --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/ReloadProjectCommand.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for reloading a project. +/// +[VisualStudioContribution] +public class ReloadProjectCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.ReloadProjectCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + const string solutionName = "ConsoleApp32"; + const string projectPath = "ConsoleApp1\\\\ConsoleApp1.csproj"; + + await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.ReloadProject(projectPath), + cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Reloaded a project called {projectPath} in solution {solutionName}.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/RenameProjectCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/RenameProjectCommand.cs new file mode 100644 index 00000000..3b797262 --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/RenameProjectCommand.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for renaming a project. +/// +[VisualStudioContribution] +public class RenameProjectCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.RenameProjectCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + var serviceBroker = context.Extensibility.ServiceBroker; + ProjectQueryableSpace querySpace = new ProjectQueryableSpace(serviceBroker: serviceBroker, joinableTaskContext: null); + var result = await querySpace.Projects + .Where(p => p.Name == "ConsoleApp1") + .AsUpdatable() + .Rename("NewProjectName") + .ExecuteAsync(cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync("Renamed Project to NewProjectName.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SetStartupProjectsCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SetStartupProjectsCommand.cs new file mode 100644 index 00000000..b97bf915 --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SetStartupProjectsCommand.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for setting startup projects. +/// +[VisualStudioContribution] +public class SetStartupProjectsCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.SetStartupProjectsCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + const string solutionName = "ConsoleApp32"; + const string projectPath1 = "ConsoleApp1\\\\ConsoleApp1.csproj"; + const string projectPath2 = "ConsoleApp2\\\\ConsoleApp2.csproj"; + + await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.SetStartupProjects(projectPath1, projectPath2), + cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Setting startup projects.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionBuildCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionBuildCommand.cs new file mode 100644 index 00000000..a8e19dc9 --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionBuildCommand.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for building the solution. +/// +[VisualStudioContribution] +public class SolutionBuildCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.SolutionBuildCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + var serviceBroker = context.Extensibility.ServiceBroker; + ProjectQueryableSpace querySpace = new ProjectQueryableSpace(serviceBroker: serviceBroker, joinableTaskContext: null); + var result = await querySpace.Solutions + .BuildAsync(cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Building the solution.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionSaveCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionSaveCommand.cs new file mode 100644 index 00000000..2a986329 --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/SolutionSaveCommand.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for saving the solution. +/// +[VisualStudioContribution] +public class SolutionSaveCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.SolutionSaveCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + var serviceBroker = context.Extensibility.ServiceBroker; + ProjectQueryableSpace querySpace = new ProjectQueryableSpace(serviceBroker: serviceBroker, joinableTaskContext: null); + var result = await querySpace.Solutions.SaveAsync(cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Saving the solution.", PromptOptions.OK, cancellationToken); + } +} diff --git a/New_Extensibility_Model/Samples/VSProjectQueryAPISample/UnloadProjectCommand.cs b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/UnloadProjectCommand.cs new file mode 100644 index 00000000..7c2c528e --- /dev/null +++ b/New_Extensibility_Model/Samples/VSProjectQueryAPISample/UnloadProjectCommand.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VSProjectQueryAPISample; + +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.Shell; +using Microsoft.VisualStudio.ProjectSystem.Query; + +/// +/// A sample command for unloading a project. +/// +[VisualStudioContribution] +public class UnloadProjectCommand : Command +{ + /// + public override CommandConfiguration CommandConfiguration => new("%VSProjectQueryAPISample.UnloadProjectCommand.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ToolsMenu }, + Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText), + }; + + /// + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + const string solutionName = "ConsoleApp32"; + const string projectPath = "ConsoleApp1\\\\ConsoleApp1.csproj"; + + await this.Extensibility.Workspaces().UpdateSolutionAsync( + solution => solution.Where(solution => solution.BaseName == solutionName), + solution => solution.UnloadProject(projectPath), + cancellationToken); + + await this.Extensibility.Shell().ShowPromptAsync($"Unloaded a project called {projectPath} in solution {solutionName}.", PromptOptions.OK, cancellationToken); + } +}