Visual Studio
A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.
5,181 questions
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I'm trying to learn how to create a keyboard shortcut on a Visual Studio 2022
extension.
I would like to get the shortcut visible and editable at Tools > Options > Environment > Keyboard
Steps i tried:
[ProvideMenuResource("Menus.ctmenu", 1)]
public static class PackageIds
.vsct
file and set the same GUID used on the button..vsct
include on the .csproj
to VSCTCompile
<ItemGroup>
<VSCTCompile Include="VSIXPackage.vsct">
<ResourceName>Menus.ctmenu</ResourceName>
<SubType>Designer</SubType>
</VSCTCompile>
</ItemGroup>
It does compile and install, when i hit Ctrl
+ W
i can see the cursor changing to the loading icon for a short period of time, but the Execute()
functio never gets called.
What i'm missing?
VSIXPackage.cs
using Microsoft;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.ComponentModel.Design;
using System.Windows;
using Task = System.Threading.Tasks.Task;
namespace VSIX;
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(VSIXPackage.PackageGuidString)]
[ProvideAutoLoad(UIContextGuids.NoSolution, PackageAutoLoadFlags.BackgroundLoad)]
public sealed class VSIXPackage : AsyncPackage
{
public const string PackageGuidString = "f9a8aea3-f579-4816-9cb5-4ae3a5d68ef7";
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
var commandService = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
Assumes.Present(commandService);
var menuCommandID = new CommandID(PackageIds.guidVSIXPackageCmdSet, PackageIds.MyCommandId);
var menuItem = new OleMenuCommand((s, e) => Execute(), menuCommandID);
commandService.AddCommand(menuItem);
}
public static void Execute()
{
MessageBox.Show("Hello World!");
}
public static class PackageIds
{
public const string CmdSetGuid = "d858b0de-b9fa-49e8-a7ae-e080d04a78be"; // Match the GUID in .vsct
public const int MyCommandId = 0x0100;
public static readonly Guid guidVSIXPackageCmdSet = new Guid(CmdSetGuid);
}
}
VSIXPackage.vsct
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable">
<Extern href="stdidcmd.h"/>
<Extern href="vsshlids.h"/>
<Commands package="guidVSIXPackagePkg">
<Groups>
<Group guid="guidVSIXPackageCmdSet" id="ButtonGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS" />
</Group>
</Groups>
<Buttons>
<Button guid="guidVSIXPackageCmdSet" id="MyCommandId" priority="0x0100" type="Button">
<Parent guid="guidVSIXPackageCmdSet" id="ButtonGroup" />
<Strings>
<CommandName>MyCommandId</CommandName>
<ButtonText>MyShortcut</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>
<KeyBindings>
<KeyBinding guid="guidVSIXPackageCmdSet" id="MyCommandId" editor="guidVSStd97" mod1="Control" key1="W" />
</KeyBindings>
<Symbols>
<!-- Define a unique GUID for your command set -->
<GuidSymbol name="guidVSIXPackagePkg" value="{908f5230-d345-4ee5-a854-d9397bfa6ede}" />
<GuidSymbol name="guidVSIXPackageCmdSet" value="{d858b0de-b9fa-49e8-a7ae-e080d04a78be}">
<IDSymbol name="ButtonGroup" value="0x1020" />
<IDSymbol name="MyCommandId" value="0x0100"/>
</GuidSymbol>
</Symbols>
</CommandTable>
VSIX.csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>{C28A9253-3A5D-41ED-A3F9-FAA709A70BD9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VSIX</RootNamespace>
<AssemblyName>VSIX</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<LangVersion>12</LangVersion>
<GeneratePkgDefFile>true</GeneratePkgDefFile>
<UseCodebase>true</UseCodebase>
<IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer>
<IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer>
<IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment>
<CopyBuildOutputToOutputDirectory>true</CopyBuildOutputToOutputDirectory>
<CopyOutputSymbolsToOutputDirectory>true</CopyOutputSymbolsToOutputDirectory>
<StartAction>Program</StartAction>
<StartProgram Condition="'$(DevEnvDir)' != ''">$(DevEnvDir)devenv.exe</StartProgram>
<StartArguments>/rootsuffix Exp</StartArguments>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VSIXPackage.cs" />
</ItemGroup>
<ItemGroup>
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Design" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.0.32112.339" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="17.12.2069" />
<PackageReference Include="System.Drawing.Common">
<Version>5.0.2</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<VSCTCompile Include="VSIXPackage.vsct">
<ResourceName>Menus.ctmenu</ResourceName>
<SubType>Designer</SubType>
</VSCTCompile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
The full extension project can be found here on GitHub.