Add Visual Studio commands
A command represented by the Command
class is some action that can be initiated by a user, such as when the user chooses a menu item, presses a toolbar button, or types a keyboard shortcut. Commands have a display name, an execution method (ExecuteCommandAsync
) that performs the action, an icon for display in the toolbar to identify the command, and a tooltip to explain the command to the user. Commands can be enabled or disabled depending on various conditions.
Commands in the new Extensibility Model run asynchronously so the user can continue to interact with the IDE while commands are executing.
Work with commands
This overview covers these top scenarios for working with commands:
- Create a command
- Place a command in the IDE
- Add an icon to a Command
- Add shortcuts to a command
- Configure a command
- Change the display name of a command
Create a command
Creating a command with the new Extensibility Model begins with extending the base class Command
, adorning the class with the VisualStudioContribution
attribute, and implementing the CommandConfiguration
property.
[VisualStudioContribution]
public class MyCommand : Command
{
/// <inheritdoc />
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%");
}
CommandConfiguration class
The CommandConfiguration
class has a few parameters that you should become familiar with:
Parameter | Type | Required | Description |
---|---|---|---|
DisplayName |
String | Yes | The default display name of your command. Surround this string with the '%' character to enable localizing this string. See at Localize metadata. |
ToolTipText |
String | No | The text to display as the tooltip when the command is hovered or focused. Surround this string with the '%' character to enable localizing this string. See at Localize metadata |
Flags | CommandFlags | No | Flags to set additional properties on the command. Some options include CanToggle and CanSelect. See at Command Flags. |
Placements | CommandPlacement[] | No | Specifies the existing groups within Visual Studio that the Command will be parented to. See at Place a command in the IDE. Even without a placement, your command will still be available via the Visual Studio Search feature. Commands can also be placed onto Menus, Toolbars, and Groups defined in your extension. |
Icon | CommandIconConfiguration | No | Commands can be displayed in the UI as either just an Icon, an Icon with text, or just text. This property configures what that icon should be, if any, and how it should be displayed. |
Shortcuts | CommandShortcutConfiguration[] | No | Defines the set of key combinations that can be used to execute the command. Shortcuts can be scoped down to only be applicable to specific IDE contexts. See at Shortcuts. |
ClientContexts[] | String | No | Client contexts requested by the command. By default the Shell and Editor contexts are returned. A client context is a snapshot of specific IDE states at the time a command was originally executed. Since these commands are executed asynchronously this state could change between the time the user executed the command and the command handler running. See at Client contexts. |
Example
The Command
also needs a constructor that takes the VisualStudioExtensibility
object (which allows communication with the IDE), and an execution method ExecuteCommandAsync
. The following example provides a minimal implementation of a generic command that doesn't do anything:
[VisualStudioContribution]
public class MyCommand : Command
{
/// <inheritdoc />
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%");
public MyCommand(VisualStudioExtensibility extensibility)
: base(extensibility)
{
}
public override Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Place a command in the IDE
There's a set of well-defined places in Visual Studio where commands can be placed. These placements are defined by the property KnownPlacements
on the class CommandPlacement
. The current set of KnownPlacements
is:
ToolsMenu
- The command will be placed in a group under the top-level "Tools" menu in Visual Studio.ViewOtherWindowsMenu
- The command will be placed in a group under the top-level "View" -> "Other Windows" menu in Visual Studio.ExtensionsMenu
- The command will be placed in a group under the top-level "Extensions" menu in Visual Studio.
Commands can also be placed using the CommandPlacement.VsctParent
method by the specifying the Guid
and Id
of group defined via VSCT.
Commands parented to the same group are sorted based on their placement's Priority
property, relative to other commands or menus with the same placement. The default Priority
value for a CommandPlacement
is 0
and can be modified by calling the CommandPlacement.WithPriority
method, passing in the desired Priority
value.
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
// The command will be parented to a group inside of the "Tools" top level menu,
// a group inside of the "Extensions" top level menu, and the "About" group inside of the "Help" top level menu
Placements = new CommandPlacement[]
{
CommandPlacement.KnownPlacements.ToolsMenu,
CommandPlacement.KnownPlacements.ExtensionsMenu.WithPriority(0x0100),
CommandPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id: 0x016B, priority: 0x0801),
},
};
Add an icon to a command
Commands support adding icons to their menu item, either in addition to or instead of the display name of the command. To add an icon to your command, set the Icon
property on your command's CommandConfiguration
.
CommandIconConfiguration
The CommandIconConfiguration
has two parameters:
Parameter | Type | Required | Description |
---|---|---|---|
IconName | ImageMoniker | Yes | You can either use a custom moniker for an image that you added following the Adding custom images section or reference a Visual Studio ImageMoniker like ImageMonikers.KnownValues.AddItem |
IconSettings | IconSettings | Yes | Configures how the command will be displayed. For example IconSettings.IconAndText displays the icon alongside the command's display name, whereas IconSettings.IconOnly will only show the command's icon and not its DisplayName if parented to a toolbar. |
ImageMoniker.KnownValues example
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
Icon = new CommandIconConfiguration(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText),
};
Use a custom image for the command icon
You can add custom images, which you can then reference with custom monikers by following these steps:
- Rename the image source files to follow the
%Custom Moniker%.*
pattern (for example, MyImage.1.png). Files prefixed with the same moniker will all be used as backing sources for the same custom moniker. Different source will be used based on the requested icon size.- For example, MyImage.16.16.png (a 16*16 png), MyImage.20.20.png (a 20*20 png) and MyImage.xaml are all considered as sources for
MyImage
. - When the requested icon size is 16*16, MyImage.16.16.png will be used, when requested size is 20*20, MyImage.20.20.png will be used, in all other cases, MyImage.xaml will be used.
- For example, MyImage.16.16.png (a 16*16 png), MyImage.20.20.png (a 20*20 png) and MyImage.xaml are all considered as sources for
- Put all of the image source files under
Images
folder.- The default image assets folder is
Images
, but you can also customize it by adding<ImageAssetsPath>%YourFolder%</ImageAssetsPath>
- The default image assets folder is
ImageMoniker.Custom example
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
Icon = new CommandIconConfiguration(ImageMoniker.Custom("MyImage"), IconSettings.IconAndText),
};
Shortcuts
Commands can be configured to be executed when a specific key combination is used. A Shortcut consists of one or two chords, where each chord consists of a ModifierKey
and one Key
. Possible values for ModifierKey
are LeftAlt
, Shift
, Control
, ControlShift
, ControlShiftLeftAlt
, and None
, where None
is only valid when used in the second chord of a shortcut. The same ModifierKey
doesn't need to be used for both chords in a Shortcut. The Key
used in a chord can be almost any other keyboard key.
Many keyboard shortcuts are already used in Visual Studio. You shouldn't assign the same shortcut to more than one command because duplicate bindings are hard to detect and may also cause unpredictable results. Therefore, it's a good idea to verify the availability of a shortcut before you assign it.
Shortcut activation constraint
An activation constraint can be included in the configuration to have the shortcut available in different contexts. These activation constraints are defined in the form of a Guid
, and usually relate to an editor. When a shortcut is given an activation constraint, it will only be available in that specific context. For example, use the Guid
"{5EFC7975-14BC-11CF-9B2B-00AA00573819}" to make the shortcut available in the Visual Studio editor. In this case the shortcut would only be available when the Visual Studio editor is focused.
Shortcut sample
public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
Shortcuts = new CommandShortcutConfiguration[]
{
new(ModifierKey.LeftAlt, Key.M),
new(ModifierKey.ControlShift, Key.Y, ModifierKey.ControlShift, Key.B),
},
};
Configure a command
You can configure visibility and the enabled/disabled state of a command, and set additional metadata using flags.
Visibility
The visibility of a command can be controlled by setting the VisibleWhen
property on your command's CommandConfiguration
.
The attribute supports specifying a condition through a number of individual parameters that together specify the condition and all its logic and inputs. To specify the condition, you specify an expression in one parameter, define a set of terms (strings) used in the expression in another parameter, and what values those terms should be replaced with upon evaluation in a third parameter. The combination of the expression, terms, and values is called a rule-based activation constraint and is fully described at Rule-based activation constraints.
If this property is omitted from your configuration, the default is for the command to always be visible.
Visibility example
public override CommandConfiguration CommandConfiguration => new("My command")
{
VisibleWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveSelectionFileName, @"\.(jpg|jpeg|txt)$"),
};
Enabled/disabled state
The enabled/disabled state of a command can be controlled by setting the EnabledWhen
property on your command's CommandConfiguration
.
This type of configuration is called a rule-based activation constraint and is fully described at Using rule based activation constraints.
If this configuration is omitted from your command, the default is for the command to always be enabled. You can also automatically have your command be disabled if it's currently executing by setting this.DisableDuringExecution = true;
in the constructor of your command class. Setting this property overrides the enabled/disabled state defined by the EnabledWhen
configuration while the command is being executed.
Enabled/disabled state example
public override CommandConfiguration CommandConfiguration => new("My command")
{
EnabledWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveSelectionFileName, @"\.(jpg|jpeg|txt)$"),
};
For more information on valid term values, see Rule-based activation constraints.
Command flags
Command flags help define additional properties on your commands that are used at runtime to define special behaviors that your command can have. The flags that are currently supported are:
CanToggle
- Indicates that theIsChecked
property of the command can change so that screen readers can announce the command properly. Functionally, it ensures that the automation propertyIsTogglePatternAvailable
returns true for the UI element.CanSelect
- Indicates that theIsChecked
property of the command can change so that screen readers can announce the command properly. Functionally, it ensures that the automation propertyIsSelectionPatternAvailable
returns true for the UI element.
Change the display name of a command
While the display name for a command is initially set in the CommandConfiguration
(see Creating a Command), it can be changed at runtime by setting the DisplayName
property in your command. The ToolTipText
property can be updated in a similar way.
Change DisplayName example
[VisualStudioContribution]
public class MyCommand : Command
{
/// <inheritdoc />
public override CommandConfiguration CommandConfiguration => new("Initial Display Name");
public MyCommand(VisualStudioExtensibility extensibility)
: base(extensibility)
{
}
public override Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
// Update the command's Display Name
this.DisplayName = "Updated Display Name";
return Task.CompletedTask;
}
}
Next steps
- Follow the create the project section in Getting Started section.
- Explore the documentation for configuring Menus and Toolbars
- Next, see the InsertGuidSample sample for a more complete look at creating an extension with a command.
- See an example of parenting a command at CommandParentingSample.