常见问题:将外接程序转换为 VSPackage 扩展

外接程序现在已弃用。 若要创建新的 Visual Studio 扩展,你需要创建 VSPackage。 如果你已经拥有外接程序,它可能仍可运行;但是,如果你想要分发它,则你应该将它转换为 VSPackage。 以下是关于如何将 Visual Studio 外接程序转换为 VSPackage 扩展的一些常见问题的解答。

重要

在大多数情况下,你只需将外接程序代码传输到 VSPackage 项目。你可以通过在 Initialize 方法中调用 GetService 获取 DTE 自动化对象。

DTE2 dte = (DTE2)GetService(typeof(DTE));

有关详细信息,请参阅下面的如何在 VSPackage 中运行我的外接程序代码?

开发 VSPackage 扩展需要哪些软件?

除了 Visual Studio 2013 专业版、高级专业版或旗舰版之外,你还需要安装 Visual Studio 2013 SDK。 你可以从“Microsoft 下载中心”网站上的 Visual Studio 2013 SDK 页面中下载 SDK。 建议你在安装 Visual Studio 2013 Update 2 之前先安装该 SDK。

VSPackage 文档位于何处?

扩展 Visual Studio 概述开始。 有关 VSPackage 开发的其他文章将组织在此文章下。

能否将我的外接程序项目转换为 VSPackage 项目?

无法将外接程序项目转换为 VSPackage 项目,因为 VSPackage 项目中使用的机制与外接程序项目中使用的机制不同。 VSPackage 项目模板包含大量使它相对容易建立并作为 VSPackage 扩展运行的代码。

如何开始开发 VSPackage 扩展?

VSPackage 扩展的项目模板具有你所需的元素。 下面是创建具有菜单命令的 VSPackage 的方法:

创建具有菜单命令的 VSPackage

  1. 创建一个 Visual Studio 程序包项目并将其命名为 TestVSPackage。 (“文件”“新建”“项目”,或在**“快速启动”窗口中键入项目)。 在“新建项目”对话框中,依次展开“其他项目类型”“扩展性”,然后选择“Visual Studio 程序包”**。 将该项目命名为 TestVSPackage 并为其指定位置。

  2. 将出现**“Visual Studio 程序包向导”。 在其“选择编程语言”页面上,选择 C# 作为语言。 使“生成新密钥”选项处于选中状态。 在“VSPackage 选项”页面上,选择“菜单命令”。 选择“完成”**按钮。

  3. 按 F5 以在调试模式下生成并运行项目。

    将出现 Visual Studio 的第二个实例。 此第二个实例称为实验实例,它具有的设置可能与你要用来编写代码的 Visual Studio 实例的设置不相同。 第一次运行实验实例时,系统将要求你登录到 VS Online 并指定你的主题和配置文件。

    在**“工具”菜单上(在实验实例中),你应该看到一个名为“我的命令名”的按钮。 当你选择此按钮时,应该会出现一条消息:“TestVSPackagePackage.MenuItemCallback() 内部”**。

如何在 VSPackage 中运行我的外接程序代码?

通常采用以下两种方式之一来运行外接程序代码:

  • 由菜单命令触发(代码位于 IDTCommandTarget.Exec 方法中)

  • 启动时自动运行(代码位于 OnConnection 事件处理程序中。)

你可以在 VSPackage 中执行相同的操作。 以下显示了如何将一些外接程序代码添加到回调方法中:

在 VSPackage 中实现菜单命令

  1. 创建具有菜单命令的 VSPackage。 (参阅如何开始开发 VSPackage 扩展?。)

  2. 打开包含 VSPackage 定义的文件。 (在 C# 项目中,它是 <your project name>Package.cs。)

  3. 将以下 using 语句添加到文件中:

    using EnvDTE;
    using EnvDTE80;
    
  4. 查找 MenuItemCallback 方法。 添加对 GetService 的调用以获取 DTE2 对象:

    DTE2 dte = (DTE2)GetService(typeof(DTE));
    
  5. 添加外接程序在其 IDTCommandTarget.Exec 方法中所具有的代码。 例如,以下是一些将新窗格添加到**“输出”**窗口并在新窗格中打印“一些文本”的代码。

    private void MenuItemCallback(object sender, EventArgs e)
    {
        DTE2 dte = (DTE2) GetService(typeof(DTE));
        OutputWindow outputWindow = dte.ToolWindows.OutputWindow;
    
        OutputWindowPane outputWindowPane = outputWindow.OutputWindowPanes.Add("A New Pane");
        outputWindowPane.OutputString("Some Text");
    }
    
  6. 生成并运行此项目。 按 F5 或选择**“调试”工具栏上的“启动”。 在 Visual Studio 的实验实例中,“工具”菜单应该具有一个名为“我的命令名”的按钮。 选择此按钮时,单词“一些文本”应该出现在“输出”窗口窗格中。 (你可能需要打开“输出”**窗口。)

你还可以使代码在启动时运行。 但是,通常反对将此方法用于 VSPackage 扩展。 如果在 Visual Studio 启动时尝试加载太多扩展,则启动时间可能会明显加长。 更好的方法是,仅在满足一些条件(例如打开解决方案)时才自动加载 VSPackage。

此过程显示了如何在打开解决方案时自动加载的 VSPackage 中运行外接程序代码:

自动加载 VSPackage

  1. 创建 Visual Studio 程序包项目。 (有关执行此操作的步骤,请参阅如何开始开发 VSPackage 扩展?。) 将该项目命名为 TestAutoload 并为其指定位置。

  2. 将出现**“Visual Studio 程序包向导”。 在“选择编程语言”页面上,选择 C# 作为语言,并使“生成新密钥”选项处于选中状态。 选择“完成”**。

  3. 打开 TestAutoloadPackage.cs。 查找声明程序包类所在的行:

    public sealed class <name of your package>Package : Package
    
  4. 此行上方是一组特性。 添加此特性:

    [ProvideAutoLoad(UIContextGuids80.SolutionExists)]
    
  5. 在 Initialize() 方法中设置断点并启动调试 (F5)。

  6. 在实验实例中,打开一个项目。 应该加载 VSPackage,并且应该命中断点。

通过使用 UIContextGuids80 的字段,可指定要在其中加载你的 VSPackage 的其他上下文。 有关详细信息,请参阅如何:自动上载 VSPackage

如何获取 DTE 对象?

如果你的外接程序无法显示 UI(例如,菜单命令、工具栏按钮或工具窗口),则只要你从 VSPackage 中获取 DTE 自动化对象,你可能就能够按原样使用代码。 操作方法如下:

从 VSPackage 中获取 DTE 对象

  1. 在 VSPackage 解决方案中,查找 <project name>Package.cs 文件。 这是派生自 Package 的类;它可以帮助你与 Visual Studio 进行交互。 在这种情况下,请使用其 GetService 来获取 DTE2 对象。

  2. 添加以下 using 语句:

    using EnvDTE;
    using EnvDTE80;
    
  3. 查找 Initialize 方法。 此方法将处理你在程序包向导中指定的命令。 添加对 GetService 的调用以获取 DTE 对象:

    DTE dte = (DTE)GetService(typeof(DTE));
    

拥有 DTE 自动化对象之后,你可以将其余的外接程序代码添加到项目中。 如果你需要 DTE2 对象,你可以执行相同的操作。

如何将我的外接程序中的菜单命令和工具栏按钮更改为 VSPackage 样式?

VSPackage 扩展使用 .vsct 文件创建大多数菜单命令、工具栏、工具栏按钮和其他 UI。 VSPackage 项目模板将为你提供用于在**“工具”**菜单上创建命令的选项。 有关详细信息,请参阅演练:使用 Visual Studio 创建包模板的菜单命令

有关 .vsct 文件的详细信息,请参阅 Vspackage 如何将用户界面元素到 IDE。 有关显示如何使用 .vsct 文件添加菜单项、工具栏和工具栏按钮的演练,请参阅命令、菜单和工具栏的演练

如何采用 VSPackage 方式添加自定义工具窗口?

VSPackage 项目模板将向你提供用于创建工具窗口的选项。 有关详细信息,请参阅工具窗口及其下面的文章,特别是如何:创建一个工具窗口

如何采用 VSPackage 方式管理 Visual Studio 窗口?

如果你的外接程序管理 Visual Studio 窗口,则外接程序代码应该在 VSPackage 中有效。 例如,此过程显示了如何将管理**“任务列表”**的代码添加到 VSPackage 的 MenuItemCallback 方法。

将外接程序中的窗口管理代码插入到 VSPackage 中

  1. 如何开始开发 VSPackage 扩展?一节所述,创建具有菜单命令的 VSPackage。

  2. 打开包含 VSPackage 定义的文件。 (在 C# 项目中,它是 <your project name>Package.cs。)

  3. 添加以下 using 语句:

    using EnvDTE;
    using EnvDTE80;
    
  4. 查找 MenuItemCallback 方法。 添加对 GetService 的调用以获取 DTE2 对象:

    DTE2 dte = (DTE2)GetService(typeof(DTE));
    
  5. 添加外接程序中的代码。 例如,以下是一些用于向**“任务列表”**添加新任务、列出任务数,然后删除一个任务的代码。

    private void MenuItemCallback(object sender, EventArgs e) 
    {
        DTE2 dte = (DTE2) GetService(typeof(DTE)); 
    
        TaskList tl = (TaskList)dte.ToolWindows.TaskList; 
        askItem tlItem; 
    
        // Add a couple of tasks to the Task List. 
        tlItem = tl.TaskItems.Add(" ", " ", "Test task 1.",  
            vsTaskPriority.vsTaskPriorityHigh, vsTaskIcon.vsTaskIconUser, 
            true, "", 10, true, true);
        tlItem = tl.TaskItems.Add(" ", " ", "Test task 2.", 
            vsTaskPriority.vsTaskPriorityLow, vsTaskIcon.vsTaskIconComment, true, "", 20, true,true);
    
        // List the total number of task list items after adding the new task items.
        System.Windows.Forms.MessageBox.Show("Task Item 1 description: "+tl.TaskItems.Item(2).Description);
        System.Windows.Forms.MessageBox.Show("Total number of task items: "+tl.TaskItems.Count); 
    
        // Remove the second task item. The items list in reverse numeric order. 
        System.Windows.Forms.MessageBox.Show("Deleting the second task item");
        tl.TaskItems.Item(2).Delete();
        System.Windows.Forms.MessageBox.Show("Total number of task items: "+tl.TaskItems.Count); 
    }
    

如何在 VSPackage 中管理项目和解决方案?

如果你的外接程序可以管理项目和解决方案,则外接程序代码应在 VSPackage 中有效。 例如,此过程显示了如何添加获取启动项目的代码。

  1. 如何开始开发 VSPackage 扩展?一节所述,创建具有菜单命令的 VSPackage。

  2. 打开包含 VSPackage 定义的文件。 (在 C# 项目中,它是 <your project name>Package.cs。)

  3. 添加以下 using 语句:

    using EnvDTE;
    using EnvDTE80;
    
  4. 查找 MenuItemCallback 方法。 添加对 GetService 的调用以获取 DTE2 对象:

    DTE2 dte = (DTE2)GetService(typeof(DTE));
    
  5. 添加外接程序中的代码。 例如,以下代码将获取解决方案中启动项目的名称。 (当此程序包运行时,多项目解决方案必须处于打开状态。)

    private void MenuItemCallback(object sender, EventArgs e)
    {
        DTE2 dte = (DTE2) GetService(typeof(DTE)); 
    
        SolutionBuild2 sb = (SolutionBuild2)dte.Solution.SolutionBuild; 
        Project startupProj; 
        string msg = "";
    
        foreach (String item in (Array)sb.StartupProjects) 
        {
            msg += item; 
        }
        System.Windows.Forms.MessageBox.Show("Solution startup Project: "+msg); 
        startupProj = dte.Solution.Item(msg); 
        System.Windows.Forms.MessageBox.Show("Full name of solution's startup project: "+"/n"+startupProj.FullName); 
    }
    

如何在 VSPackage 中设置键盘快捷方式?

请使用 .vsct 文件的 <KeyBindings> 元素。 在以下示例中,命令 idCommand1 的键盘快捷方式是 Alt+A,命令 idCommand2 的键盘快捷方式是 Alt+Ctrl+A。 请注意键名的语法。

<KeyBindings>
    <KeyBinding guid="MyProjectCmdSet" id="idCommand1" editor="guidVSStd97" key1="A" mod1="ALT" />
    <KeyBinding guid="MyProjectCmdSet" id="idCommand2" editor="guidVSStd97" key1="A" mod1="CONTROL" mod2="ALT" />
</KeyBindings>

如何在 VSPackage 中处理自动化事件?

在 VSPackage 中采用与外接程序中相同的方法处理自动化事件。 以下代码显示了如何处理 OnItemRenamed 事件。 (本示例假设你已经获得 DTE 对象。)

Events2 dteEvents = (Events2)dte.Events;
dteEvents.ProjectItemsEvents.ItemRenamed += listener1.OnItemRenamed; 
. . .
public void OnItemRenamed(EnvDTE.ProjectItem projItem, string oldName) 
{
    string s = "[Event] Renamed " + oldName + " to " + Path.GetFileName(projItem.get_FileNames(1) + " in project " + projItem.ContainingProject.Name; 
}