如何运用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版本的功能。
###参考步骤
-
首先在vs里创建一个类库的项目
-
添加引用选择下载好的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的作者,提供了一个这么好的工具。
如果你也遇到类似问题不知道怎么处理,可以留言沟通交流下。
欢迎扫描关注公众号