日期:2014-05-17  浏览次数:21151 次

VS插件编写初探
很久没来C#版,特来散下分。
CSDN的blog系统确实太烂,本文图片使用ikaca相册,不保证能够显示。
排版的话就将就吧


  本文以一个简单的 VS 插件的编写过程来对 VS 自动化模型进行简单的介绍。这个 VS 插件有以下功能:调用 Google 搜索代码编辑器中选中的文本。

  在代码编辑器中选中文本后单击鼠标右键能弹出如下图所示的菜单: 


建立 VS 外接程序的方法非常简单,像普通的 Windows Application 一样, VS 已经提供了完整的向导帮助我们建立 Addin 程序。

通过选择文件菜单、新建、项目打开新建项目对话框,然后选择 “ 其他项目类型 ” 、 “ 扩展性 ” ,选择 “Visual Studio 外接程序 ” 打开外接程序向导。 

以 VS2008 为例,打开向导后选择“下一步”出现下图: 

选择 C# ,接着根据提示选择支持的 VS 版本: 

填写项目名称和说明,出现下面得对话框,

如果想要创建菜单项,可以选中第一项,向导将自动生成相关的代码,建议选中,因为向导所生成的代码可以作为添加更多菜单时代码的模板,而且,所生成的代码支持多种语言。

如果想要外接程序在 VS 启动的时候自动加载,可以选中第二项。如果没有选中此项,可以手动修改工程目录下的 “ 工程名 .AddIn” 文件。该文件其实是 xml 格式的文件,用于配置外接程序的选项,使用记事本或其他文本编辑工具打开,修改此项为 1 即可: <LoadBehavior>0</LoadBehavior> 


这样,便生成了一个外接程序的项目,我们可以修改、编写代码完成外接程序。此时的代码已经可以编译运行,运行后,在 VS 的外接程序管理器中将可以插件的有关项。 

选中加载插件,便可以在工具菜单中看到名为 “SearchGoogle” 的菜单项。 

接下来,我们为插件在代码编辑器中添加右键菜单项,首先,先使用单例模式创建一个类,用于保存生成的右键菜单项对象,大致代码如下:
C# code
namespace SearchOnWeb
{
  public sealed class InternalInfo
  {

    private static InternalInfo internalInfo = null;

    public static InternalInfo GetInternalInfoInstance()
    {
      if (internalInfo == null)
      {
        internalInfo = new InternalInfo();
      }
      return internalInfo;
    }

    private InternalInfo()
    {
      this.pop = null;
    }

    private CommandBarPopup pop;

    public CommandBarPopup Pop
    {
      get { return pop; }
      set { pop = value; }
    }

  }
}



创建菜单项的基本步骤如下:

代码应使用 try … catch 块,否则,当 VS 加载插件时遇到异常将不再执行后面的代码,导致插件加载失败。

l 创建一个 Command 对象,通过调用 _applicationObject.Commands.AddNamedCommand2 方法实例化 Command 对象。

l 通过 AddControl 方法把命令添加到对应的 CommandBar 中。

l 在 QueryStatus 方法中添加相应代码,使得菜单可见。(重要,否则看不见菜单 )

l 在 Exec 方法中添加相应代码,使菜单执行相应功能。

 

首先,打开 Connect.cs ,在 OnConnection 方法中添加代码。先查找代码编辑器的右键菜单的 CommandBar 对象:

CommandBars commandBars = ((CommandBars)_applicationObject.CommandBars);

CommandBar commandBar = (CommandBar)commandBars["Code Window"];

创建并实例化一个 CommandBarPopup ,设置相应的参数,添加第一级菜单项“ SearchOnWeb ”: 


对象创建后,再加入二级菜单“ Google… ”: 


要添加多个命令,重复上面的步骤,创建多个 Command 对象并添加到 this.internalInfo.Pop.CommandBar 中。

 

接下来,我们需要在 QueryStatus 方法中添加相应代码,使得菜单可见: 


在 QueryStatus 方法中,我们通过 commandName 判断具体为哪一个菜单, commandName 的命名规则为:

  namespace 名称 .Connect.Command 名称

  如: SearchGoogle.Connect.SearchOnGoogle

 

最后,为菜单添加执行代码, 在调用菜单时, VS 执行 Exec 方法,与 QueryStatus 相同,我们通过 commandName 对菜单项进行判断,菜单被点击后将调用 Exec 函数执行相应的代码。 
C# code
public void Exec(string commandName, vsCommandExecOption executeOption,
            ref object varIn, ref object varOut, ref bool handled)
{
        handled = false;
        if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
        {
            if (commandName == "SearchOnWeb.Connect.SearchOnGoogle")
            {
                this.goSearchGoogle();
                handled = true;
                return;
            }
        }
}



SearchGoogle.Connect.SearchOnGoogle 的具体执行代码将在后文描述。

 

前面我们已经完成了菜单的添加,与 Windows 程序不同,外接程序不是一个独立的程序,也就是说虽然我们退出了 AddIn 程序,但是 VS 可能仍然在运行,这时,我们在 VS 中添加的各种控件、菜单项、窗口等都不会随着我们 AddIn 程序的退出而被卸载,因此,资源回收是 AddIn 必须处理的问题。下面讨论菜单项的卸载。

如果退出了 AddIn ,而菜单没有删除,那么便可能出现这种情况,当我们在此启用 AddIn 时, AddIn 又添加了一个新的一样的菜单项,这样,出现的是两套相同的菜单项,显然不是我们想要的。于是