如何运用netoffice,开发兼容多个版本的outlook插件

如何运用netoffice,开发兼容多个版本的outlook插件

###需求描述
用户使用outlook发送邮件时,如果收件人包含公司外的人员,则弹出提醒,确认是否发送。
###思考
首先思考到outlook插件,基于C#开发的话,会依赖.netframework等版本环境,并且outlook版本也很多兼容性,所以和领导确认了一下,仅做win7及以上操作系统,.netframework 4.0以上版本。
###开始干活
因为第一次做outlook插件,而且很久没有接触过C#开发,所以第一想法还是借助百度。
虽然搜索资料很多,但是大部分都是用的VSTO来实现的outlook插件,下载VS2017然后开始创建项目,发现创建这个时候outlook版本就已经有要求了,心里一凉,觉得兼容性应该很麻烦。

看了一些别人的博客,然后很快用VSTO实现了第一个版本,本地测试后,发现一切正常,本地是outlook2010版本,然后再另外两个同事那里安装测试,悲剧就开始了,首先是.netframwork版本不能低于4.0,然后提示缺少vs office tools工具,很是头疼。。。期间折腾了下载VS的各种版本等等,特别无语。

###摸索
因为一直在做java开发,也不清楚C#的outlook插件兼容性要怎么解决,还是一直百度,基本看遍了网上相关的论坛,帖子,微软的MSDN等等。后来发现有人遇到了同样的兼容性问题,然后了解到有个开源的netoffice,这里附上旧的地址,链接:https://archive.codeplex.com/?p=netoffice 新的地址已经迁移到GitHub:https://github.com/NetOfficeFw/NetOffice

依仗着谷歌浏览器自带的页面翻译,把这个工具对应的问题讨论、等等都看了一遍。然后参考着官网的例子,终于写出了2.0版本的功能。

###参考步骤

  1. 首先在vs里创建一个类库的项目

  2. 添加引用选择下载好的NetOffice.dll,Office.dll,Outlook.dll,extensibility.dll
    编写代码内容如下:

    using System;
    using System.Runtime.InteropServices;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using NetOffice;
    using NetOffice.Tools;
    using Outlook = NetOffice.OutlookApi;
    using NetOffice.OutlookApi.Enums;
    using NetOffice.OutlookApi.Tools;
    using Office = NetOffice.OfficeApi;
    using NetOffice.OfficeApi.Enums;
    using NetOffice.OfficeApi.Tools;
    
    namespace test008
    {
    [COMAddin("test008", "test008", 3), ProgId("test008.Addin"), Guid("9774342E-E2F0-4557-9137-8DA2B7720285")]
    [RegistryLocation(RegistrySaveLocation.CurrentUser)]
    public class Addin : Outlook.Tools.COMAddin
    {
    	public Addin()
    	{
    		this.OnStartupComplete += new OnStartupCompleteEventHandler(Addin_OnStartupComplete);
    		this.OnDisconnection += new OnDisconnectionEventHandler(Addin_OnDisconnection);
           
            
    	}
    
    private void Addin_OnStartupComplete(ref Array custom)
    {
       
        Outlook.Application application = this.Application;
        application.ItemSendEvent += new Outlook.Application_ItemSendEventHandler(ItemSend_BeforeSend);
        
        
    }
    private void ItemSend_BeforeSend(object Item, ref bool Cancel)
    {
        
        Outlook.MailItem mailItem = (Outlook.MailItem)Item;
    
        if (mailItem != null)
        {
            String toEmails = GetSMTPAddressForRecipients(mailItem);
            if (!"".Equals(toEmails))
            {
                String otherCompanyEmails = "";//用于存放是否包含外部人员邮箱,默认为空
                String[] regMatch = { "*****.cn" };//用于存放公司已有的邮箱后缀,全部为小写。
                String[] emails = toEmails.ToLower().Split(';');
    
                if (emails != null && emails.Length > 0)
                {
                    int emailCount = emails.Length;
                    for (int i = 0; i < emailCount; i++)
                    {
                        if ("".Equals(emails[i].Trim()))
                        {
                            continue;
                        }
                        Boolean isExistOtherCompany = true;//默认认为都是公司外部人员邮箱
                        for (int k = 0; k < regMatch.Length; k++)
                        {
                            if (emails[i].IndexOf(regMatch[k]) >= 0)
                            {
                                isExistOtherCompany = false; //匹配到公司邮箱则跳出循环继续下一个判断
                                break;
                            }
                        }
                        if (isExistOtherCompany)
                        {
                            otherCompanyEmails = otherCompanyEmails + emails[i] + ";";
                        }
                    }
                    if (!"".Equals(otherCompanyEmails))
                    {
                        DialogResult dr = MessageBox.Show("您的收件人中包含其他公司人员邮箱:" + otherCompanyEmails.Replace(';', ' ') + ",确认发送吗?", "温馨提示", MessageBoxButtons.OKCancel);
                        if (dr == DialogResult.OK)
                        {
                            //用户选择确认的操作
    
                            Cancel = false;
    
                        }
                        else if (dr == DialogResult.Cancel)
                        {
                            //用户选择取消的操作
    
                            Cancel = true;
                        }
                    }
                }
            }
    
    
        }
    
    }
    //获取收件人和抄送人员的邮箱信息,并自动用;间隔
    private String GetSMTPAddressForRecipients(Outlook.MailItem mailItem)
    {
        String result = "";
        const string PR_SMTP_ADDRESS =
            "http://schemas.microsoft.com/mapi/proptag/0x39FE001E";
        Outlook.Recipients recips = mailItem.Recipients;
        foreach (Outlook.Recipient recip in recips)
        {
            Outlook.PropertyAccessor pa = recip.PropertyAccessor;
            string smtpAddress =
                pa.GetProperty(PR_SMTP_ADDRESS).ToString();
            result = result + smtpAddress + ";";
        }
        return result;
    }
    
    
    private void Addin_OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
    {
    }
    
    protected override void OnError(ErrorMethodKind methodKind, System.Exception exception)
    {
    	MessageBox.Show("An error occurend in " + methodKind.ToString(), "test008");
    }
    
    [RegisterErrorHandler]
    public static void RegisterErrorHandler(RegisterErrorMethodKind methodKind, System.Exception exception)
    {
    	MessageBox.Show("An error occurend in " + methodKind.ToString(), "test008");
    }
    }
    }
    

###又遇到问题了
按照网上其他帖子说法,编写之后,修改项目的属性,在生成里面,需要勾选为COM互操作注册,但是我这个如果勾选,则项目启动会提示一个引入的错误,网上建议说要调整互操作类型选项。
另外因为项目的目标框架定为了.net Framework 3.5 ,所以引入的文件没有修改嵌入互操作类型选项,修改XML文件也没有生效,所以取消勾选为COM互操作注册选项,不知道会不会引发其他问题,然后本地调试启动了outlook之后,本地功能生效了,outlook加载项中,会出现我创建好的test008dll。

###继续遇到新问题
高兴了一小会之后,发现,怎么把这个生成的dll文件给其他人注册使用呢?第一个想法想到了注册表,然后一顿折腾,根本不行。之后又尝试了wix,install sheild之类的N多的打包工具,然后也没有达到我想要的效果。
后来又看微软的官网,等等,继续逛netoffice的问题,最后看到一个人提交一个问题,说自己的dll插件注册之后没有生效。莫非是我注册的不对了?
查看N多信息之后,最后发现是用错了命令,.netframework 4.0会有一个regAsm.exe的文件,直接执行regAsm.exe ***.dll文件即可。。。。各种-_-||。。。
最后又看了下bat文件的语法怎么编写执行,最终终于写出了一个安装脚本,然后在其他人电脑上运行,暂时没发现问题。

最后感谢下netoffice的作者,提供了一个这么好的工具。
如果你也遇到类似问题不知道怎么处理,可以留言沟通交流下。

欢迎扫描关注公众号
如何运用netoffice,开发兼容多个版本的outlook插件_第1张图片

你可能感兴趣的:(C#)