如何使用.NET开发全版本支持的Outlook插件产品(一)——准备工作

这半年一直在做Outlook的插件,因为不会VC++,所以想找一款基于.NET,用C#开发Outlook插件的技术方案。没想到,光技术选型这件事,就用各种技术手段验证了将近一个月,还花费了大量的精力做之后的各项开发工作。在此开个大坑,以此记录所有的技术成果,如果以后还有别的朋友要做Outlook,甚至于Office插件,都可以从这儿作为起步,因为Office插件的基础技术都是一致的,只是到了各个产品内部COM对象有特性差异。

好了,废话不多说,我们开始正文。

技术选型

如果提到要做Office插件,大家都会去网上找,当然最快得到的一个应该就是VSTO。虽然我们最后没有采用这个方案,但是我还是想在这儿稍微介绍一下它,因为它有自己非常强大的优点。

VSTO是Visual Studio Tools for Office的简称,在我看来,是和Visual Studio集成得最棒的插件开发SDK。如果你下载安装了VSTO,并且你使用Visual Studio的话,你会在创建项目的一开始就找到“Office插件”项目类型,之后有一系列的交互界面来引导你一步一步创建一个符合你要求的插件基础类型,甚至最后连界面都可以用所见即所得的方式进行设计——当然后台的代码也是完全面向对象的,你可以用最方便的方法来快速制作一个插件并进行打包部署。如果你的最终目标只是做一个为企业内部部署,并且你可以控制安装部署发布甚至面向特定Outlook版本的话,我强烈推荐你采用它,因为我一直奉行适用就是完美,不需要为了追求无意义的技术专精而采用其它方案。

但是,如果你像我一样,要做一款需要适用于各个操作系统(当然是XP以上,2000啥的咱就不提了),还需要支持所有Outlook版本(2003以上),还需要完全控制安装部署等一系列后续事宜,完全把这个插件当做一个产品为开发目标的话,VSTO这件看起来很美好的东西实际用起来不一定那么美好,原因有以下几点:

  1. 无法控制的面向对象版本——VSTO是针对固定Office版本的,如果你下载了2013版的,那很可能无法兼容2003。
  2. 无法适应多版本——在使用VSTO的时候,是无法针对各个版本来定制界面的。大家知道从Office 2010开始,菜单就采用了Ribbon样式,而2007以下还都是经典菜单栏。事实上,你无法在使用VSTO的情况下来为这些版本定制不同的界面,这非常复杂。
  3. 无法控制的发布——众所周知,你一开始用了MS的东西,后面不用都不行,简直就是一个黑洞。如果你用了VSTO作为开发框架,那打包很可能就是InstallShield(现在最新版的VS里面已经没有Installation Project了,而且InstallShield是收费的)。而这东西你完全不知道如何才能控制它的行为,让它在x86和x64上都能成功部署插件。要知道,Office插件是需要写注册表键值才能成功安装的。

好了,既然用现成的东西走不通,我们就索性找找开源免费的东西吧。幸好,我们找到了最后的技术方案(中间经历的痛苦和大量技术验证工作真是无法用文字形容),NetOffice和Wix。

 

基础框架

NetOffice是一套开源的,基于.NET的Office插件开发框架,大家可以访问下面的链接来下载它。

http://netoffice.codeplex.com/

NetOffice支持多个.NET版本,从2.0到4.5都有,因此已经涵盖我们现有的所有.NET版本。

我们最后的选型是3.5,这里面也是经过慎重推敲的。3.5版本的.NET Framework是从Windows 7开始支持的,对于Windows 7以上版本的操作系统,都可以不需要安装.Net Framework就可以运行。但是有一点只有是做.NET的人都知道,就是3.5安装包的尺寸非常大,难道要用户下载安装这么大的基础库包吗?我们的解决方案是,发布的时候,不带.NET Framework。那如果是XP用户怎么办?我们的安装包自动下载安装4.0版本.NET Framework。我们就用这种方法成功解决了兼容性和下载精简性的两难问题。再说了,现在微软马上就不再支持XP的持续更新了,XP的生命说实话真的进入倒计时了,我们也不要再在这样的系统上花费更多精力了。

Wix在我另外的博文里面也有介绍,是一款非常好用的打包安装框架。当然之前我的文章里面对它的介绍太为肤浅,这次,我们将它翻了一个底朝天。现在,我们已经可以做到这样的安装了。在这次的技术介绍中,我也会对Wix的高级使用开发进行详细讲解。应该可以涵盖几乎所有的打包安装Case,方便大家以后更高效得制作更优秀的安装包。下面的截图我进行了一些打码处理,因为毕竟涉及商业问题,请各位见谅。

1

创建工程环境

有了以上的框架技术基础,我们就可以来创建我们的第一个Outlook插件项目了,因为我现在用的是Office 2013,我们先做一个简单的Outlook 2013插件好了。其实这个插件2010也能用,因为插件UI是用Ribbon。

我们先用“管理员身份”运行Visual Studio。因为我们开发的是一个COM类型的类库,而这个类库需要向注册表注入一些键值,VS需要管理员身份才能自动完成这些操作。你问怎么用管理员身份运行?在图标上右键点击,展开的菜单里面就有。

然后我们创建一个“类库”项目,我们起个项目名称叫“TestOutlookAddin”,记得.NET的版本是3.5。随后我们添加NetOffice相应3.5版本的以下dll文件引用:

extensibility.dll

NetOffice.dll

OfficeApi.dll

OutlookApi.dll

我们再调整解决方案的编译环境,必须要有x86和x64两种。因为插件是对Office版本敏感的,x64的Office只能加载x64编译得到的插件dll,同样的,x86版本Office也只能加载x86版本dll。

我们还要对项目进行属性设置。

在“应用程序”标签页中,点击“程序集信息…”,在打开的对话框中勾选“使程序集COM可见”。

在“生成”标签页中,勾选“为COM互操作注册”。

在“调试”标签页中,将“启动操作”勾选“启动外部程序”,并且填入你机器上的Outlook.exe启动路径,在我的机器上,路径如下:

C:Program FilesMicrosoft OfficeOffice15OUTLOOK.EXE

修改完这个以后,我们先进入C:Program FilesMicrosoft OfficeOffice15,也就是Outlook.exe的所在文件夹,看看有没有outlook.exe.config文件。如果没有这个文件,请创建这个文件,并在文件里面写入以下XML

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v1.0.3705" />
    <supportedRuntime version="v1.1.4322" />
    <supportedRuntime version="v2.0.50727" />
  </startup>
</configuration>

这个文件必须和Outlook.exe在同一个文件夹中。如果没有这个文件,我们将无法进入调试状态。我想没有人能在不调试的情况下编写一整个插件吧?

编写样例代码

我们把环境的装备工作做好了,下面就来编写最简单的插件。

我们先在项目中创建一个RibbonUI.xml,并把它的生成操作定义为“嵌入的资源”,内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<customUI onLoad="LoadAction"  xmlns="http://schemas.microsoft.com/office/2006/01/customui" >
  <ribbon>
    <tabs>
      <tab id="RibbonAddinSampleTabCS35" label="插件标签">
        <group id="group1" label="分组名">
          <button id="customButton1" size="large" label="按钮"/>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

对于Outlook 2007以上的版本来说,这个文件就是定义新增的菜单栏界面的。

然后再在项目中创建一个名为COMEntry的类,代码如下:

using System.Runtime.InteropServices;
using NetOffice.OutlookApi.Tools;
using NetOffice.Tools;

namespace TestOutlookAddin
{
    [COMAddin("Test Addin For Outlook", "", 3), CustomUI("TestOutlookAddin.RibbonUI.xml"), RegistryLocation(RegistrySaveLocation.CurrentUser)]
    [Guid("AFE67651-951D-4A42-8CAB-E9BF7E219DDF"), ProgId("TestAddinForOutlook")]
    public class COMEntry : COMAddin
    {
    }
}

其中COMAddin特性类声明了一系列需要加载和插件初始化的信息,它的参数有“插件在Outlook插件列表中的显示名称”,“插件在列表中的描述”,“启动类型(3代表跟随Outlook启动而自动启动)”。

CustomUI表示了刚才我们定义的RibbonUI.xml作为嵌入的资源的资源访问路径,这点对于有一定经验的.NET开发人员一定不陌生。

RegistryLocation是定义了插件在注册表中注册到哪个根键值里面去。我们知道现在Windows安装文件都有“仅为我”和“所有人”安装选项,这个特性也是为了区分它的。不过这个仅仅是在调试状态下,因为发布的时候这个键值还是会由我们的安装包来自行控制,所以不需要在这个地方做过多纠结。

好了,我们在VS按下F5调试查看一下效果吧,如下图

image

我们得到了一个新的标签,标签内部有个新的分组和空白的“按钮”,鼠标移到按钮上,就会自动出现下面的弹出说明框。

在此,需要先进行一个声明,下方的这个弹出说明框是可以自定义标题和内容的,但是最下方的插件名称超链接和“详细信息”是无法去掉的。微软官方的解释是:为了区分这个到底是一个第三方插件还是Outlook自身自带的按钮。因为他们担心一些质量很差的插件影响了Outlook自身的行为,用户还要怪罪到微软头上。因此他们就用这种方法来明显区别插件和自身控件了。

现在我们已经得到了最初始版本的插件,当然现在什么事情都不能做。在下一篇中,我们将谈谈如何定位插件的部署错误,以及对插件进行更多的自定义操作。

原文地址:https://www.cnblogs.com/vanpan/p/3583920.html