你的第一个 Visual Studio 扩展

本文将引导你完成一些简单的步骤,以便启动并运行第一个 Visual Studio 扩展。 Visual Studio 扩展是使用 .NET Framework 和 C# 编写的。 如果你已经是 .NET 开发人员,你会发现编写扩展类似于编写大多数其他 .NET 程序和库。

今天要编写的扩展会添加一个命令,该命令在执行时将新 GUID 插入文本编辑器中。 它非常简单、有用,并很好地介绍了扩展开发的各个方面。

如果你是视觉学习者,请检查本教程后面的某人的此简短视频。

在开始编写第一个 Visual Studio 扩展(这很容易,我承诺!)之前,请确保你已获得 所需的工具。

创建项目

有几个项目模板可供选择,因此你想要做出正确的选择。 此社区工具包中使用的模板名称中都有名字对象(社区)。

VSIX 项目 w/Command (Community) 模板附带了一个已挂钩的命令,因此可以轻松地从那里开始。 对于大多数扩展而言,这是一个很好的起点。 如果知道需要工具窗口,请使用 VSIX 项目 w/Tool Window (社区) 模板。 它还具有用于打开工具窗口的命令。

将空 VSIX 项目(社区)VSIX 项目(社区)模板用于仅限 MEF 的扩展或其他高级方案。

这次,你将选择 VSIX 项目 w/Command (Community) 模板,如下面的屏幕截图所示。

New Project Dialog showing VSIX project templates.

选择项目模板后,需要为项目命名。 将其命名为 InsertGuid

Configure your new project.

点击 “创建 ”按钮后,最终应会看到如下所示的基本 VSIX 项目:

New project files and folders.

重要文件

我们来看看最重要的文件。

InsertGuidPackage.cs 称为 Package 类。 Visual Studio 调用其 InitializeAsync(...) 方法来初始化扩展。 从此处可以添加事件侦听器并注册命令、工具窗口、设置和其他内容。

source.extension.vsixmanifest 是扩展的清单文件。 它包含元数据,如标题和说明,但也包含有关扩展包含的内容的信息。

VSCommandTable.vsct 是一个 XML 文件,其中以声明方式定义命令和键绑定,以便它们可以注册到 Visual Studio。

Commands/MyCommand.cs 是 VSCommandTable.vsct 文件中定义的命令的命令处理程序。 它通过单击按钮来控制命令执行时会发生什么情况。

修改命令

首先,你需要确保命令在 Visual Studio 菜单系统中具有正确的名称、图标和位置。

打开 VSCommandTable.vsct 文件,找到一个<Group>和一个 <Button>。 请注意该按钮如何将组指定为其父组,并且该组的父级是内置的 VSMainMenu/Tools 菜单。

对于扩展,需要“插入 GUID”命令按钮位于“编辑”主菜单下,因此需要将组重新父级到“编辑”菜单。 将工具替换为“编辑”,就像在以下代码片段中一样:

<Group guid="InsertGuid" id="MyMenuGroup" priority="0x0600">
  <Parent guid="VSMainMenu" id="Edit"/>
</Group>

你可以获得完整的 IntelliSense 位置,以便轻松找到合适的位置。

VSCT parent IntelliSense.

还需要 <Button> 更新。 通过将元素的属性<Icon>更新idPasteAppend 来为其提供一个新图标。 使用 <ButtonText> 良好的描述性名称更新文本,并使用命令的技术名称进行更新 <LocCanonicalName> - 这是当用户在 “工具 > 选项 > 环境 > 键盘 ”对话框中为命令分配自定义键盘快捷方式时向用户显示的名称。

<Button guid="InsertGuid" id="MyCommand" priority="0x0100" type="Button">
  <Parent guid="InsertGuid" id="MyMenuGroup" />
  <Icon guid="ImageCatalogGuid" id="PasteAppend" />
  <CommandFlag>IconIsMoniker</CommandFlag>
  <Strings>
    <ButtonText>Insert GUID</ButtonText>
    <LocCanonicalName>.Edit.InsertGuid</LocCanonicalName>
  </Strings>
</Button>

注意

始终以 <LocCanonicalName> 点字符开头。 它确保不会自动预写其他文本,并且不会显示点。

可以使用 Visual Studio 图像库中提供的数千个图标,甚至可以获取 IntelliSense 中显示的预览:

VSCT icon IntelliSense.

现在,你已更新命令的名称、图标和位置,现在可以编写一些代码以将 guid 插入文本编辑器中。

打开 /Commands/MyCommand.cs 文件并将其修改为在执行时插入新的 guid:

using System;
using Community.VisualStudio.Toolkit;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Task = System.Threading.Tasks.Task;

namespace InsertGuid
{
    [Command(PackageIds.MyCommand)]
    internal sealed class MyCommand : BaseCommand<MyCommand>
    {
        protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)
        {
            await Package.JoinableTaskFactory.SwitchToMainThreadAsync();
            DocumentView docView = await VS.Documents.GetActiveDocumentViewAsync();
            if (docView?.TextView == null) return;
            SnapshotPoint position = docView.TextView.Caret.Position.BufferPosition;
            docView.TextBuffer?.Insert(position, Guid.NewGuid().ToString()); 
        }
    }
}

你正在使用该 VS 对象获取活动编辑器文本视图,然后将 guid 插入到其文本缓冲区的插入点位置。

注意

你将在此社区工具包的很多位置看到和ThreadHelper.ThrowIfNotOnUIThread()显示await JoinableTaskFactory.SwitchToMainThreadAsync()。 它们处理线程切换最佳做法,目前不需要知道何时以及如何使用这些做法 - 使用代码修复(灯泡)的编译器警告使这一点变得非常简单。

扩展的第一个草稿现已完成,是时候测试它了。

运行和调试

运行扩展与运行任何其他 .NET 项目一样简单。 只需按 F5 即可在附加调试器的情况下运行,或者 按 Ctrl+F5 运行而不运行。

这样做将启动已安装扩展的 Visual Studio 实验实例。 实验实例是 Visual Studio 的常规版本,但安装了单独的设置和扩展。 它有助于使事情保持分开。

实验实例启动时,应在“编辑”主菜单中看到“插入 GUID”命令

Insert GUID command located in the Edit main menu.

打开任何基于文本的文件并执行命令以插入新的 guid。 就这么简单!

总结

现已创建第一个扩展,该扩展将命令按钮添加到主菜单,并在执行时与文本编辑器交互。

祝贺!!

可以在示例存储库中找到此扩展的代码。