新版 Visual Studio 的发布往往都会为扩展(包、加载项、模板等)的开发者带来挑战。例如,Visual Studio 2010 引入了新的 Visual Studio 扩展安装程序(VSIX 文件);Visual Studio 2012 引入了浅色/深色主题;Visual Studio 2015 删除了加载项(和加载项管理器);更不用说每一版 Visual Studio 引入的新 SDK、新扩展性程序集和新 API。随着 Visual Studio 2017 发布,这一挑战甚至更为严峻,因为其中引入了基于工作负载和各个组件的新模块化安装程序,以及适用于 VSIX 部署机制的新版清单。
虽然一些开发者(主要是 Microsoft 开发者)为每个 Visual Studio 发行版本发布不同的新扩展,但大多数开发者更倾向于发布一个更新后扩展,以定目标到最广范围的 Visual Studio 发行版本。
本文将介绍如何完成此任务。为此,我将把重心放在以下最常见情境上:含命令的包,在托管语言(在此示例中为 C#)中创建,并部署为 VSIX 文件。
要实现以下目标:
使用一个 Visual Studio 项目创建包。
使用 Visual Studio 2017 进行开发和调试。
生成一个包 DLL 作为生成结果。
将单个 DLL 放入一个 VSIX 文件中。
能够在 Visual Studio 2017 及多个更低发行版本(2015、2013 等)上安装 VSIX 文件。
由于需要用到两个项目(作为包的 DLL 文件和作为包部署工具的 VSIX 文件),我将分别介绍以下两方面:首先,它们在安装或运行时的工作方式;其次,如何开发它们。
如前所述,Visual Studio 2010 引入了用于安装 Visual Studio 扩展的 VSIX 部署机制,自那以后成为首选方式。
VSIX 文件的扩展名为 .vsix,可以通过不同方式进行安装。如果 VSIX 文件在 Visual Studio Marketplace(前身为 Visual Studio 库)上发布,并且与要使用的 Visual Studio 发行版本和版本兼容,那么可以使用“扩展和更新”对话框安装此文件。
在“工具”菜单下,单击“扩展和更新”,再依次转到“在线”和“Visual Studio Marketplace”(见图 1“‘扩展和更新’对话框窗口”)。
图 1:“扩展和更新”对话框窗口
还可以双击 VSIX 文件。这样,可以执行与 .vsix 文件扩展相关的 Visual Studio 启动器 (C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\VSLauncher.exe);此操作可以找到已安装最高发行版本 Visual Studio 的 VSIXInstaller.exe 实用工具(安装所有较低发行版本需要的最高发行版本)。
然后,VSIX 安装程序显示图 2“VSIX 安装程序”中的对话框,以便可以选择将扩展安装到的兼容 Visual Studio 发行版本和版本。
图 2:VSIX 安装程序
也可以编程方式安装 VSIX 文件,只需结合使用 VSIXInstaller.exe 实用工具和命令行选项,如目标 Visual Studio 发行版本(2017、2015 等)和版本(Community、Professional 等)。可以在 Visual Studio 安装内容的 Common7\IDE 子文件夹中找到此实用工具。
无论采用哪种安装方式,Visual Studio 或 VSIXInstaller.exe 实用工具都需要知道 VSIX 文件支持的 Visual Studio 发行版本和版本。可以通过 VSIX 文件内的清单文件找到此类信息。VSIX 文件实际上是 .zip 文件,因此可以将 .vsix 文件扩展重命名为 .zip,再打开文件来检查其内容(见图 3“VSIX 文件内容”)。
图 3:VSIX 文件内容
可以看到,VSIX 文件内含多个文件:.dll file 是包 DLL。.pkgdef 文件在安装时用于向 Windows 注册表添加一些键,以便 Visual Studio 将 DLL 识别为包。
[Content_Types].xml 文件描述各个文件扩展(.dll、json 等)的内容类型。Visual Studio 2017 需要 catalog.json 和 manifest.json 文件。extension.vsixmanifest 文件描述扩展名称和发行版本等,以及支持的 Visual Studio 发行版本和版本。
可以解压缩 extension.vsixmanifest 文件,并使用文本编辑器打开它,从而检查文件内容,如图 4“清单文件内容”所示。
图 4:清单文件内容
可以看到,清单在 InstallationTarget XML 元素中声明了支持的 Visual Studio 版本。其中的 Microsoft.VisualStudio.Pro 值定目标到 Professional 版本及更高版本,如 Premium、Ultimate、Enterprise 以及其他所有此类版本。
请注意,此值还定目标到 Community 版本,此版本基本上就是 Professional 版本,不同之处在于存在一些许可限制和不具备某些功能。此值还声明了支持的 Visual Studio 发行版本范围:10.0 (2010)、11.0 (2012)、12.0 (2013)、14.0 (2015)、15.0 (2017)。
安装每用户扩展的 VSIX 文件(通过 Visual Studio 或 VSIX 安装程序)后,内部所含文件被解压缩并复制到以下位置的随机文件夹中:C:\Users\\AppData\Local\Microsoft\VisualStudio\\Extensions\。 可以包含“实验实例”(稍后介绍)对应的“Exp”后缀,并且对于 Visual Studio 2017,其中还包含已安装 Visual Studio 的“实例 ID”。
此实例 ID 是在 Visual Studio 安装时随机生成;之所以包含它是为了支持并行安装同一发行版本 Visual Studio (2017) 的不同版本,以前无法提供这样的支持。对于整个计算机范围内的扩展,使用的是子文件夹 Common7\IDE\Extensions。
请注意,在任何情况下,每个 Visual Studio 发行版本都对它的扩展使用自己的文件夹。
虽然最好能够所有 Visual Studio 发行版本都支持同一清单格式,但遗憾的是,情况并非如此。Visual Studio 2010 引入了 VSIX 和第 1 版清单。Visual Studio 2012 引入了第 2 版清单,完全不同于第 1 版且互不兼容。
不过,虽然 Visual Studio 2012、2013 和 2015 全都支持第 2 版,但仍可以接受第 1 版清单,因此可以使用第 1 版清单生成 VSIX 文件,并从 Visual Studio 2010 定目标到 Visual Studio 2015。
但 Visual Studio 2017 既不支持第 1 版,也不支持第 2 版。相反,它需要的是第 3 版清单。幸运的是,第 3 版继续在 PackageManifest XML 元素的 Version 属性中使用值“2.0.0.0”,只添加了名为 的 XML 元素(并向 VSIX 文件添加了两个新文件,即 catalog.json 和 manifest.json)。
因此,它与第 2 版保持完全向后兼容,受到 Visual Studio 2012、2013 和 2015 的支持(但不受 Visual Studio 2010 的支持,它仅支持第 1 版)。也就是说,不能用一个 VSIX 文件定目标到 Visual Studio 2010-2017。
从这一点出发,我将放弃 Visual Studio 2010,并将继续使用支持 Visual Studio 2012、2013、2015 和 2017 的 VSIX 文件。
托管的 Visual Studio 包是 DLL,其中包含继承自 Microsoft.VisualStudio.Shell.Package 的类。它装饰有特定属性,这些属性有助于在生成时生成 .pkgdef 文件(如前所述,可以在 VSIX 文件内和扩展的安装文件夹中找到此文件)。
.pkgdef 文件在启动时(旧版 Visual Studio)或安装时(Visual Studio 2017 发行版本 15.3),用于将 DLL 注册为 Visual Studio 包。注册后,Visual Studio 便会尝试在某时刻加载此包,此时刻可能是启动时,也可能是执行它的命令之一时(如果包使用延迟加载的话,这是最佳做法)。
在尝试加载托管的 DLL 并初始化包期间,将会发生三件事:Microsoft .NET Framework 版本的公共语言运行时 (CLR) 加载 DLL;它使用 .NET Framework 提供的一些 DLL;它还会使用 Visual Studio 提供的一些 DLL。我将逐件进行介绍。
.NET Framework 是以下两项的总和:CLR + 库(基类和其他库)。CLR 为运行时(JIT 编译器、垃圾回收器等),负责加载托管的 DLL。很久之前,每个 .NET Framework 版本 1.0、1.1 和 2.0(供 Visual Studio.NET 2002、Visual Studio.NET 2003 和 Visual Studio 2005 使用)都提供自己的 CLR 版本(1.0、1.1 和 2.0)。
不过,Visual Studio 2008 使用的 .NET Framework 3.0 和 3.5 继续使用完全相同的 CLR 2.0 版本 .NET Framework 2.0,而不是引入新版本。Visual Studio 2010 引入了 .NET Framework 4 和 CLR 4.0,但从那以后,所有新的 .NET Frameworks 4.x 都使用 CLR 4.0(尽管“就地”替换为向后兼容的版本,而不是重用确切的 CLR 4.0 版本 .NET Framework 4)。
由于 Visual Studio 2012 及更高版本都使用 CLR 4.0,因此如果扩展 DLL 定目标到 Visual Studio 2012、2013、2015 和 2017,CLR 版本并不是问题。
库构成了 .NET Framework 的第二部分;这些是 Visual Studio 项目引用的 DLL,以及在运行时使用的 DLL。若要开发一个定目标到多个 Visual Studio 发行版本的扩展,必须使用要定目标到的最低 Visual Studio 发行版本默认安装的最高版本 .NET Framework。也就是说,若要定目标到 Visual Studio 2012 及更高版本,需要使用 .NET Framework 4.5。
例如,不能使用 Visual Studio 2013 引入的 .NET Framework 4.5.1,因为此版本中引入的任何 DLL 都不会出现在仅安装 Visual Studio 2012 的计算机上。除非真正需要这个 DLL,否则无需强制此类用户安装 .NET Framework 4.5.1 才能使用扩展(可能会对销售额或下载和支持造成不利影响)。
扩展还需要 Visual Studio 提供的 DLL(通常命名为 Microsoft.VisualStudio.*)。在运行时,Visual Studio 会在一些已知位置查找 DLL,如文件夹 Common7\IDE 及其子文件夹 Common7\IDE\PublicAssemblies 和 Common7\IDE\PrivateAssemblies,以及全局程序集缓存 (GAC)。
.NET Framework 4.x 的 GAC 位于 C:\Windows\Microsoft.NET\assembly(还有一个 GAC 位于 C:\Windows\assembly,但它适用于旧版 .NET Framework)。Visual Studio 2017 使用的是更独立的安装,可以避免 GAC,而不依赖前述文件夹。
开发和生成 VSIX 文件时,需要遵循以下两个关键原则:必须使用扩展定目标到的最低 Visual Studio 发行版本提供的发行版本。也就是说,若要定目标到 Visual Studio 2012 及更高版本,只能使用此发行版本(或更低版本)提供的程序集和扩展性 API。
如果扩展使用 Visual Studio 2013 或更高版本引入的 DLL,将无法在仅安装 Visual Studio 2012 的计算机上运行。第二个原则是,扩展绝不能将 Visual Studio DLL 部署到我提到的位置(Visual Studio 文件夹或 GAC),也不能部署到扩展的安装文件夹。这些 DLL 是由目标 Visual Studio 提供。也就是说,VSIX 文件不得包含它们。
许多 Visual Studio DLL 的名称中有版本号 (8.0 … 15.0),如 Microsoft.VisualStudio.Shell.11.0.dll 或 Microsoft.VisualStudio.Shell.Immutable.10.0.dll。这些有助于识别引入它们的 Visual Studio 发行版本,但请不要上当,这是名称,而不是版本。
例如,Microsoft.Visual.Studio.Shell.11.0.dll 有四个版本(11.0.0.0、12.0.0.0、14.0.0.0 和 15.0.0.0),分别由 Visual Studio 发行版本 2012、2013、2015 和 2017 提供。前三个版本(11.0.0.0 到 14.0.0.0)分别由 Visual Studio 发行版本在 GAC 中进行安装,而 Visual Studio 2017 使用的第四个版本 15.0.0.0 在 Common\IDE\PrivateAssemblies 文件夹中进行安装。
由于定目标到 Visual Studio 2012 及更高版本的扩展必须使用版本 11.0.0.0 的 Visual Studio 程序集(前面提到的第一个原则),因此引用 Microsoft.Visual.Studio.Shell.11.0.dll 必须是版本 11.0.0.0。因为此版本并非由 Visual Studio 2013 及更高版本进行安装(从版本 12.0.0.0 开始),而且扩展不得部署 Visual Studio DLL(第二个原则),难道扩展就无法使用 Visual Studio DLL 了吗? 答案是不会,这是归功于 .NET Framework 提供的程序集绑定重定目标机制,可方便指定“若有请求要获取此版程序集,使用它的更高版本”等规则。
当然,新版本必须与旧版本保持完全向后兼容。将程序集从一个版本重定目标到另一版本的方法有几种。其中一种方法是:可执行文件(文件扩展名为 .exe)可以提供随附的配置文件(文件扩展名为 .exe.config),用于指定重定目标。
因此,如果转到 Visual Studio 安装内容的 Common7\IDE 文件夹,将会找到 Visual Studio 的 devenv.exe 可执行文件和 devenv.exe.config 文件。如果使用文本编辑器打开 .config 文件,将会看到其中包含许多程序集重定目标:
"Microsoft.VisualStudio.Shell.11.0"
publicKeyToken="b03f5f7f11d50a3a"
culture="neutral"/>
"15.0.0.0"/>
因此,Visual Studio 2017 (15.0) 有一个 Microsoft.VisualStudio.Shell.11.0 程序集版本重定目标,指明只要有请求要获取旧版本 2.0.0.0 到 14.0.0.0,则改用新版本15.0.0.0。这就是 Visual Studio 2013 或更高版本如何使用引用 Microsoft.VisualStudio.Shell.11.0 版本 11.0.0.0 的扩展;即使未提供确切的版本,也不例外。
至此,已了解运行时的具体工作方式,现在可以开发包了。总结一下,将使用 Visual Studio 2017 通过定目标到 Visual Studio 发行版本 12.0-15.0 的清单创建 VSIX 项目;其中包含包和命令;只会引用 Visual Studio 2012 安装的版本 11.0.0.0(或更低版本)。
此时,可能会问,应在开发计算机上安装哪些 Visual Studio 发行版本。最佳做法是使用两台开发计算机,如下所示:在第一台计算机上,如果有足够的磁盘空间,请安装所有的 Visual Studio 发行版本,即 2012、2013、2015 和 2017。所有这些发行版本可以并行共存,并能在开发过程中对它们进行测试。
对于 Visual Studio 2017,即使是不同的版本(如 Community、Professional 和 Enterprise),也可以同时共存,但旧版 Visual Studio 则不行。如果可用空间是一个问题,可以安装旧版的最简组件,或在范围中跳过一些发行版本(2013 或 2015)。
在第二台开发计算机上,仅安装 Visual Studio 2017,或最好使用未安装 Visual Studio 发行版本的生成服务器(仅安装了生成工具 2017),生成扩展以供发布。这种方法有助于确保未在无意间使用文件夹中旧版 Visual Studio 安装的 DLL 或其他依赖项。
可能还会问,在仅安装 Visual Studio 2012 的计算机上开发或生成内容是否不安全,答案是否定的:若要生成 Visual Studio 2017 的 VSIX 文件(创建第 3 版清单,并添加 catalog.json 和 manifest.json 文件),需要使用 Visual Studio 2017 的 Visual Studio SDK 15.0,或 Visual Studio 2015 的 Visual Studio SDK 14.0(需要完成一些工作)。
不管是 Visual Studio 2013 的 Visual Studio SDK 12.0,还是 Visual Studio 2012 的 Visual Studio SDK 11.0,都无法生成 Visual Studio 2017 的 VSIX 文件。
为了能够进行(严格)测试的最佳做法是:对每个 Visual Studio 发行版本单独使用一台计算机(虚拟或基于云),这样就需要在四台计算机上单独测试从 Visual Studio 2012 到 Visual Studio 2017 的扩展。此最佳做法帮助我在本文的代码示例中找到了一些错误!
若要获取用于创建包(或其他任何类型扩展)的 Visual Studio 2017 项目模板,需要运行“Visual Studio 扩展开发”工作负载。如果在首次安装 Visual Studio 2017 时没有安装它,请转到文件夹 C:\Program Files (x86)\Microsoft Visual Studio\Installer,启动 vs_Installer.exe,单击“修改”按钮,并选择列表底部的工作负载。
依次选择“文件”、“新建”和“项目”菜单,新建 VSIX 项目;依次转到“Visual C#”和“扩展性模板”;确保已选择顶部下拉列表中的“.NET Framework 4.5”;再选择“VSIX 项目”模板。将项目命名为“VSIXProjectVS2012_2017”。双击 source.extension.vsixmanifest 文件,打开自定义编辑器。
在“元数据”选项卡中,设置产品名称、创建者、版本等。在“安装目标”选项卡中,单击“编辑”按钮,选择“Microsoft.VisualStudio.Pro”标识符(此值也定目标到 Community 版本,此版本基本上就是 Professional 版本),并设置目标安装范围 [11.0,15.0],如图 5 所示。方括号表示包含界限值。
括号表示不包含界限值,因此也可以设置 [11.0,16.0)。还可以使用生成号(如 15.0.26208.1)定目标到次要版本(如 15.3)。
图 5:安装目标
在“依赖项”选项卡中,删除所有项。在“先决条件”选项卡中,单击“编辑”按钮,并设置扩展需要的最简 Visual Studio 2017 组件。
在此示例中,只需要使用 Visual Studio 核心编辑器。此部分是针对 Visual Studio 2017 和第 3 版清单的新增内容,因此仅适用于版本 15.0(见图 6“先决条件”):
图 6:先决条件
右键单击“解决方案资源管理器”中的 VSIX 项目节点,向 VSIX 项目添加包,再依次选择“添加”和“新建项”菜单,以调出“添加新项”对话框。
现在,依次转到“Visual Studio C# 项”、“扩展性”和“VSPackage”节点,选择“Visual Studio 包”模板,并命名为“MyPackage.cs”。向包添加命令,重复执行上一步操作,但这次选择的是“自定义命令”模板。将此模板命名为“MyCommand1.cs”。
为了遵循使用最少必需依赖项的原则,在 MyPackage.cs 和 MyCommand1.cs 的源代码中,删除未使用的(灰显)命名空间。然后,右键单击“解决方案资源管理器”中的 VSIX 项目节点,再单击“管理解决方案 NuGet 包”条目。在“已安装”部分中,按以下顺序卸载所有包:
Microsoft.VisualStudio.Shell.15.0
Microsoft.VisualStudio.Shell.Framework
Microsoft.VisualStudio.CoreUtility
Microsoft.VisualStudio.Imaging
Microsoft.VisualStudio.Shell.Interop.12.0
Microsoft.VisualStudio.Shell.Interop.11.0
Microsoft.VisualStudio.Shell.Interop.10.0
Microsoft.VisualStudio.Threading
Microsoft.VisualStudio.Shell.Interop.9.0
Microsoft.VisualStudio.Shell.Interop.8.0
Microsoft.VisualStudio.TextManager.Interop.8.0
Microsoft.VisualStudio.Shell.Interop
Microsoft.VisualStudio.TextManager.Interop
Microsoft.VisualStudio.Validation
Microsoft.VisualStudio.Utilities
Microsoft.VisualStudio.OLE.Interop
(请勿卸载 Microsoft.VSSDK.BuildTools 包,即 Visual Studio SDK。)
在“解决方案资源管理器”的项目“引用”节点中,卸载剩余所有引用(未作为 NuGet 包获得),System 和 System.Design 除外。现在可以重新生成解决方案。将会看到编译错误,只需添加图 7 中的引用,即可修复这些错误。
图 7:Visual Studio 2012 引用
程序集名称 | 程序集版本 | Visual Studio 2012 SDK 子文件夹 |
Microsoft.VisualStudio.OLE.Interop | 7.1.40304.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop | 7.1.40304.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop.8.0 | 8.0.0.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop.9.0 | 9.0.0.0 | v2.0 |
Microsoft.VisualStudio.Shell.Interop.10.0 | 10.0.0.0 | v2.0 |
Microsoft.VisualStudio.Shell.Immutable.10.0 | 10.0.0.0 | v4.0 |
Microsoft.VisualStudio.Shell.11.0 | 11.0.0.0 | v4.0 |
遗憾的是,Microsoft 并没有为 Microsoft.VisualStudio.Shell.11.0 提供官方 NuGet 包(不过,可以找到非官方 NuGet VSSDK.Shell.11 包)。
如果已安装 Visual Studio 2012(如果这是扩展支持的最低发行版本,应安装),那么可以从 GAC 中获取,如前所述。
此外,也可以安装 Visual Studio 2012 SDK (bit.ly/2rnGsfq),在文件夹 C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies 的子文件夹 v2.0 和 v4.0 中获取所需的全部程序集。上表的最后一列显示的是,可以在 Visual Studio 2012 SDK 的哪个子文件夹中找到各个程序集。
为了避免对非官方 NuGet 包或特定本地文件夹的依赖(不管是通过 Visual Studio SDK,还是通过 Visual Studio 安装),最佳做法是从任意位置获取程序集,并在项目的根文件夹下创建一个名为“VS2012Assemblies”的文件夹。
然后,将 DLL 复制到此文件夹,并从中引用它们(使用项目“引用管理器”对话框的“浏览”按钮),再将 VS2012Assemblies 文件夹添加到源代码管理中,确保将 DLL 添加到其中(通常情况下,源代码管理工具默认不添加 DLL)。因此,从这一点出发,所需的 Visual Studio 程序集属于源代码。
为了遵循不在 VSIX 文件(甚至是输出文件夹)中添加程序集引用的原则,选择各个引用,并在属性窗口中确保将“复制本地属性”设置为“False”。
此时,可以重新生成解决方案,而不会出错。使用 Windows 资源管理器,转到输出文件夹。只需生成以下文件:extension.vsixmanifest、VSIXProjectVS2012_2017.dll、VSIXProjectVS2012_2017.pkgdef 和 VSIXProjectVS2012_2017.vsix。
生成项目时,其中一个 MSBuild 目标将扩展部署到 Visual Studio 的实验实例。这是与普通实例使用不同文件夹和注册表项的 Visual Studio 实例,以免在开发期间扩展出现问题时,普通实例无法使用。
(可以随时重置实验实例,具体方法为单击 Windows“开始”按钮,输入“重置”,并执行“重置 Visual Studio 2017 实验实例”命令。) 如果转到项目“属性”页的“调试”选项卡,可以将“启动外部程序”字段设置为 Visual Studio 2017 devenv.exe 文件。(若要升级,请务必执行此更改,因为它会定目标到旧版 Visual Studio。) 还可以看到,命令行参数将“Exp”指定为根后缀(见图 8“调试实验实例”),这样实验实例就还能用于调试。
图 8:调试实验实例
依次单击“调试”和“开始调试”菜单条目,这将启动新的 Visual Studio 实例(注意描述文字是否为“实验实例”)。如果单击“工具”和“调用 MyCommand1”菜单条目,将加载此包,执行命令,并显示消息框。
若要使用 Visual Studio 2017 在旧版 Visual Studio 上调试扩展,需要进行以下两项更改:首先,因为扩展在生成后便会部署到此发行版本(其中,SDK 用于生成项目)的 Visual Studio 实验实例中,所以需要删除 NuGet 包 Microsoft.VSSDK.BuildTools 版本 15.0,并对 Visual Studio 2015 使用版本 14.0,或对 Visual Studio 2013 使用版本 12.0。对于 Visual Studio 2012,VSDK 没有任何对应的 NuGet 包,因此需要编辑 .csproj 文件,并将 VSToolsPath 变量指向 VSSDK 11.0 的位置 C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0(必须单独进行安装)。
其次,需要转到项目“属性”页的“调试”选项卡,并将“启动外部程序”字段设置为匹配的 Common7\IDE\devenv.exe 可执行文件。
大家也许知道,许多 Visual Studio 项目支持往返。也就是说,它们可以由多个 Visual Studio 发行版本进行打开和调试,而无需进行任何修改。这与扩展性项目的“现成性”有所不同。 不过,通过对 MSBuild 和 Visual Studio SKD 的些许掌握,可以实现它,但这始终都是一种非常棘手的方法。
完成开发和调试后,便可以在发布配置中生成扩展,并在测试计算机的独立实例中的已安装 Visual Studio 发行版本上测试扩展。如果一切顺利,可以在 Visual Studio Marketplace 上发布扩展!
Carlos Quintero 14 次荣获 Microsoft 最有价值专家奖,目前负责 Visual Studio 和开发技术类别。自 2002 年以来,他一直在帮助其他开发者创建 Visual Studio 扩展。
从 2006 年起,他开始写博客 visualstudioextensibility.com
Twitter 上发推文 @VSExtensibility
衷心感谢以下技术专家对本文的审阅:Justin Clareburt、Alex Eyler 和 Mads Kristensen
想看英文原版戳“阅读原文”吧