Visual Studio 2008 可扩展性开发(三):Add-In运行机制解析(上)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

前言

上一篇随笔Macro和Add-In初探介绍了如何开发两者的HelloWorld程序。没错,宏确实简单易行。不过在某些情况下,比如在商业软件中,宏在性能和知识产权方面可能会带来麻烦,此时那把更好的锤子是Add-In。

初探一文中,我介绍了如何使用Add-In向导来开发第一个Add-In。VS是一款很棒的开发工具,它的各种向导(以及其它模板、可视化工具等)做得非常好,不过我发现这一强大之处到头来反而给人诟病。其中一种说法是,这些方便的工具让初学者入门容易,并惯坏了他们,以致于想登堂入室就难得多了。客观地说,这不是VS的错,VS没有阻止你去了解这些工具的背后所在。这些工具会生成大量代码,我们需要主动去了解它们,《程序员修炼之道》中曾提到:

Don't Use Wizard Code You Don't Understand

很明显,作者不是说不能使用向导,而是说要在了解向导的前提下使用它。尤其是你写的代码要跟向导生成的代码混在一起的时候,这些代码终究要变成你的代码,而Add-In的开发正是如此!所以我们必须得先了解Add-In向导做了些什么。

Add-In向导在收集信息

Add-In向导共有六步,每一步我们都可以输入一定的信息,告诉VS如何设置。这可以看作是向导收集信息的过程,这些信息包括:

  • 编程语言:可以选择C#、VB.NET、VC,如果是手工编写Add-In,就没这个限制了
  • 宿主环境:Add-In可同时运行在不同版本的VS IDE和/或Macro IDE内
  • 名称和描述
  • 菜单命令:VS据此生成一些代码,在Tools菜单中添加一个新的菜单项
  • 命令行运行支持:这样的Add-In说明它不会呈现需要用户介入的UI,如模式对话框
  • 启动时加载:VS可以在启动时自动加载Add-In
  • About对话框:可以将Add-In的信息显示在About对话框中

信息收集完毕后,VS会生成一个新的Add-In项目。

Add-In项目

Add-In项目是一个类库项目(可以参考初探一文中做的例子),仅此而已。该项目包含了“Connect.cs”文件,它定义了Connect类,还有一个配置文件FirstAddin.AddIn。

打开Connect.cs,我们仔细分析一下。Connect类实现了两个接口,一是IDTExtensibility2,该接口用于在Add-In和IDE之间进行通信;二是IDTCommandTarget,如果选择了向导中的UI选项,就需要实现它。

IDTExtensibility2包含5个方法:

  • OnConnection:在加载Add-In时调用
  • OnStartupComplete:在Add-In随着VS的启动完成加载后调用
  • OnAddInsUpdate:在VS加载或卸载Add-In时调用
  • OnBeginShutdown:在VS关闭时调用
  • OnDisconnection:在卸载Add-In时调用

在文件顶部可以看到引用了若干个命名空间,对于Add-In开发来说最重要的是其中三个:Extensibility、EnvDTE和EnvDTE80。Extensibility定义了IDTExtensibility2使用的类型;后面两个命名空间则定义了自动化对象模型(Automation Object Model,以下简称AOM)中的类型。

回到前面的5个方法,最重要的一个是OnConnection,VS在加载Add-In时调用它,通过第一个参数application将AOM的根对象传入,向导产生的代码将该对象的引用保存_applicationObject中;同时通过第三个参数addInInst将当前Add-In所对应的AddIn对象传入,保存在_addInInstance中。再往下看,这些代码将向Tools菜单添加一个菜单命令(如果你在向导中选中该选项的话),其中包括如下代码:

ExpandedBlockStart.gif C# Code
if(connectMode == ext_ConnectMode.ext_cm_UISetup)
{
}


connectMode参数的值表示Add-In是如何加载的。如果Add-In通过菜单命令加载,那么该参数的值为ext_ConnectMode.ext_cm_UISetup。

对于另外4个方法,向导没有产生任何代码。而对于IDTCommandTarget接口的两个方法QueryStatus和Exec,则添加必要的代码来管理菜单命令以及命令点击事件的处理。Connect类中就这些内容了,那我们在向导中选择的宿主环境、名称描述等信息放在哪里呢?

.Addin文件

在我们的例子中可以看到,有个文件FirstAddin.AddIn,Add-In通过这个文件向VS进行注册。来看看它的结构如何。

它本质上是XML文件(就像模板和Code Snippet的配置文件一样):

复制代码
ExpandedBlockStart.gif XML Code - Add-In配置信息
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">
    
<HostApplication>
        
<Name>Microsoft Visual Studio</Name>
        
<Version>9.0</Version>
    
</HostApplication>
    
<Addin>
        
<FriendlyName>MyFirstAddin</FriendlyName>
        
<Description>MyFirstAddin, it's so exciting!</Description>
        
<Assembly>FirstAddin.dll</Assembly>
        
<FullClassName>FirstAddin.Connect</FullClassName>
        
<LoadBehavior>0</LoadBehavior>
        
<CommandPreload>1</CommandPreload>
        
<CommandLineSafe>0</CommandLineSafe>
    
</Addin>
</Extensibility>
复制代码


这些信息主要分为3类:

1)宿主环境

通过<HostApplication>节点来配置该Add-In适用于哪些宿主环境,该节点数目、顺序不限。在<Name>节点中说明宿主环境的名称,除了Microsoft Visual Studio还可以是Microsoft Visual Studio Macros,也就是Macros IDE;在<Version>节点中说明支持的版本,还可以是7.1、8.0,也可以用*表示支持所有版本。

2)Add-In信息

<Addin>节点指定了Add-In本身的信息。它可以包含如下子节点:

  • <FriendlyName>:可选的,为Add-In指定一个有意义的名称;
  • <Description>:可选的,为Add-In指定有意义的描述信息;
  • <AboutBoxDetails>和<AboutIconData>:都是可选的,如果要在About对话框中显示Add-In的话,该节点用于指定其详细信息和图标;
  • <Assembly>:必填的,Add-In所在的程序集;
  • <FullClassName>:必填的,指定程序集内实现了IDTExtensibility2接口的类,要使用完全限定名称;
  • <LoadBehavior>:可选的,指定VS加载Add-In的方式,0表示VS不会自动加载,必须手工加载;1表示Add-in在VS启动的时候加载;4表示通过命令行方式加载;
  • <CommandPreload>:可选的,指定Add-In应当预先加载;
  • <CommandLineSafe>:可选的,指定Add-In是否是命令行安全的以及是否显示用户界面。

3)选项页(Tools Options Page)信息

我们可以很容易地在VS的Tools -> Options对话框中添加自己的选项页,从而对Add-In进行配置,不过这里先行略过,在后续的随笔中将会介绍。

CommandBar.resx

除了Connect.cs和.AddIn文件,还有一个文件是CommandBar.resx,这里面存放了一个命令条(CommandBar)的文本值的列表。它针对的是不同的自然语言,实际上在Connect.cs中,在获取Tools菜单时就用到了它。

想一想,现在有了一个编译好的程序集还有.Addin配置文件,那VS就有足够的信息来启动、管理Add-In了。问题是,把这两个文件放在哪里呢?在项目当中有一个FirstAddin - For Testing.AddIn文件,这个文件存放的位置是[My Documents Path]\Visual Studio 2008\Addins,在我们按下F5测试Add-In的时候VS就是使用这个文件来加载的,查看它里面的配置可以看到它指向的程序集正是当前项目编译后的程序集。所以我们的Add-In编译完毕后,FirstAddin - For Testing.Addin删掉,把程序集和FirstAddin.Addin文件拷贝到[My Documents Path]\Visual Studio 2008\Addins下,就算是一种最简单的部署了。

加载和管理Add-In

在生成Add-In后,需要把它加载进VS。如果你在向导中选择在VS启动时加载,那么VS会在每次启动时自动加载Add-In。如果选择通过菜单命令加载,你也可以打开VS后,通过Add-In Manager(菜单Tools -> Add-In Manager)修改相关的设定。

addin-manager  

我们身在何处?

本文主要关注的是Add-In向导所产生的代码,其中的重点是Connect.cs和.Addin文件。Connect类是Add-In的实现类,有了它一个程序集才得以成为一个Add-In;.Addin文件中包含了Add-In的配置信息,VS以此来管理Add-In。有了这些,我们对Add-In的运行机制就有了更清楚的认识,在下一篇随笔中,我将介绍Add-In中的生命周期和事件。

参考

《Professional Visual Studio® 2008 Extensibility》
《Working with Microsoft Visual Studio® 2005》


本文转自一个程序员的自省博客园博客,原文链接:http://www.cnblogs.com/anderslly/archive/2009/02/28/vs-addin-explained-part1.html,如需转载请自行联系原作者。

目录
相关文章
|
4天前
|
Java 程序员 开发者
Java中的异常处理机制深度解析
本文旨在深入探讨Java中异常处理的核心概念与实际应用,通过剖析异常的本质、分类、捕获及处理方法,揭示其在程序设计中的关键作用。不同于常规摘要,本文将直接切入主题,以简明扼要的方式概述异常处理的重要性及其在Java编程中的应用策略,引导读者快速把握异常处理的精髓。
|
2天前
|
安全 Java 开发者
Java并发编程中的锁机制解析
本文深入探讨了Java中用于管理多线程同步的关键工具——锁机制。通过分析synchronized关键字和ReentrantLock类等核心概念,揭示了它们在构建线程安全应用中的重要性。同时,文章还讨论了锁机制的高级特性,如公平性、类锁和对象锁的区别,以及锁的优化技术如锁粗化和锁消除。此外,指出了在高并发环境下锁竞争可能导致的问题,并提出了减少锁持有时间和使用无锁编程等策略来优化性能的建议。最后,强调了理解和正确使用Java锁机制对于开发高效、可靠并发应用程序的重要性。
13 3
|
6天前
|
Java 开发者
深入解析Java中的异常处理机制
本文将深入探讨Java中异常处理的核心概念和实际应用,包括异常的分类、捕获、处理以及最佳实践。我们将通过具体示例展示如何有效使用try-catch块、throws关键字和自定义异常类,以帮助读者更好地理解和应用Java异常处理机制。
11 1
|
7天前
|
Java 程序员 开发者
Java中的异常处理机制深度解析
本文旨在深入探讨Java中异常处理的机制,包括异常的分类、如何捕获和处理异常,以及自定义异常的最佳实践。通过实例讲解,帮助读者更好地理解如何在Java编程中有效管理和利用异常处理来提高代码的健壮性和可维护性。
|
20天前
|
JavaScript 前端开发 API
探索移动应用的世界:从开发到操作系统的深入解析
【8月更文挑战第31天】本文将带你走进移动应用的世界,从开发到操作系统,深入探讨移动应用的开发过程、移动操作系统的工作原理以及它们之间的交互。我们将通过代码示例,让你更好地理解移动应用的开发和运行机制。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和知识。
|
20天前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
80 0
|
20天前
|
区块链 C# 存储
链动未来:WPF与区块链的创新融合——从智能合约到去中心化应用,全方位解析开发安全可靠DApp的最佳路径
【8月更文挑战第31天】本文以问答形式详细介绍了区块链技术的特点及其在Windows Presentation Foundation(WPF)中的集成方法。通过示例代码展示了如何选择合适的区块链平台、创建智能合约,并在WPF应用中与其交互,实现安全可靠的消息存储和检索功能。希望这能为WPF开发者提供区块链技术应用的参考与灵感。
35 0
|
20天前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
55 0
|
20天前
|
开发者 云计算 数据库
从桌面跃升至云端的华丽转身:深入解析如何运用WinForms与Azure的强大组合,解锁传统应用向现代化分布式系统演变的秘密,实现性能与安全性的双重飞跃——你不可不知的开发新模式
【8月更文挑战第31天】在数字化转型浪潮中,传统桌面应用面临新挑战。本文探讨如何融合Windows Forms(WinForms)与Microsoft Azure,助力应用向云端转型。通过Azure的虚拟机、容器及无服务器计算,可轻松解决性能瓶颈,满足全球用户需求。文中还提供了连接Azure数据库的示例代码,并介绍了集成Azure Storage和Functions的方法。尽管存在安全性、网络延迟及成本等问题,但合理设计架构可有效应对,帮助开发者构建高效可靠的现代应用。
15 0
|
20天前
|
C# Windows 开发者
超越选择焦虑:深入解析WinForms、WPF与UWP——谁才是打造顶级.NET桌面应用的终极利器?从开发效率到视觉享受,全面解读三大框架优劣,助你精准匹配项目需求,构建完美桌面应用生态系统
【8月更文挑战第31天】.NET框架为开发者提供了多种桌面应用开发选项,包括WinForms、WPF和UWP。WinForms简单易用,适合快速开发基本应用;WPF提供强大的UI设计工具和丰富的视觉体验,支持XAML,易于实现复杂布局;UWP专为Windows 10设计,支持多设备,充分利用现代硬件特性。本文通过示例代码详细介绍这三种框架的特点,帮助读者根据项目需求做出明智选择。以下是各框架的简单示例代码,便于理解其基本用法。
59 0

热门文章

最新文章

推荐镜像

更多