Outlook 插件開發小結


  最近實習在做outlook插件開發,閱讀了一些VSTO的相關概念和知識。遂將整理所得與大家分享和交流。PS:這篇博客為本人的第一篇正式技術博客,如有錯誤和不妥之處請讀者見諒。

  

 I.基本介紹

  1.VSTO外接程序體系結構

             

 

  2.Outlook add-in注冊表項

    1.Microsoft Office 2010 應用程序可加載在 HKEY_LOCAL_MACHINE 或 HKEY_CURRENT_USER 下注冊的外接程序。默認情況下,2007 Microsoft Office system 中的應用程序只能加載在 HKEY_CURRENT_USER 下注冊的外接程序。

    2.外接程序注冊表項位於所有應用程序(Visio 除外,它的 根 為 HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE)的以下注冊表項之下:Root\Software\Microsoft\Office\應用程序名稱\Addins\外接程序ID(外接程序ID一般為項目名)

    3.Outlook 窗體區域的注冊表項:Root\Software\Microsoft\Office\Outlook\FormRegions\消息類

 

  3.安裝部署

    1. ClickOnce 部署:僅當前用戶可以注冊外接程序。這是因為 ClickOnce 只支持在 HKEY_CURRENT_USER 下創建密鑰。

    2. Windows Installer部署:無限制

 

  4.定制項

   UI方面

   1.自定義UI

   2.窗體區域/ribbon:與outlook界面相整合

   邏輯方面

   1.與outlook PIA或其他office PIA進行交互

   2.自定義屬性:用於用戶自定義數據和擴展功能

 

  5.outlook對象模型

   Application 對象

   Application 對象表示 Outlook 應用程序,它是 Outlook 對象模型中最高級的對象。

 

   Explorer 對象

   Explorer 對象表示顯示包含項(如電子郵件、任務或約會)的文件夾內容的窗口。Explorer 對象包括可用來修改窗口的方法和屬性,以及窗口更改時所引發的事件。

 

   Inspector 對象

   Inspector 對象表示顯示單個項(如電子郵件、任務或約會)的窗口。Inspector 對象包括可用來修改窗口的方法和屬性,以及窗口更改時所引發的事件。

 

   MAPIFolder 對象

   MAPIFolder 對象表示包含電子郵件、聯系人、任務及其他項的文件夾。Outlook 提供 16 個默認 MAPIFolder 對象。

 

   MailItem、AppointmentItem、TaskItem、ContactItem分別對應郵件項、約會項、任務項、聯系人項

 

  6.卸載

    1.手動刪除(控制面板\程序\卸載程序)

    2.刪除注冊表(其實並未完整卸載,只是outlook不能檢測到。控制面板\程序中仍有該插件信息)

    3.禁用插件(推薦:使outlook將插件禁用,但保留在加載項欄中。想重用時可以手動啟用。)

    后兩項都能用代碼完成。

  

 II.實例講解

  以下demo在VS 2010下完成。

 

  1.VS 為office拓展程序開發提供了很好的開發項。創建OutlookAddIn:File->New->Project->Visual C#->Office->2010(2007)->Outlook 2010 Add-in.

   

  2.命名好工程名確認后,系統會自動生成ThisAddIn類以及一些相應的事件。而ThisAddIn類就是整個拓展程序的一個抽象表示。

  

  3.現在,我們可以添加自己的定制項。這里我首先添加一個窗體區域(FormRegion),窗體區域的特點是可以將該區域嵌入到outlook的工作區。右擊工程名->Add->New Item->Outlook Form Region.點擊確認后會進入FormRegion的導航設置  框。分別有一下幾項:

    一.創建方式:創建新窗體區域/從已有窗體區域導入(這里選擇前者)

    二.窗體樣式:按窗體位置和區域分有四種樣式(這里選擇第二項:adjoining加在工作窗體的底部)

    三.添加描述和呈現喜好(這里選擇默認)

    四.選擇呈現該窗體區域的消息類。由於我們是要做一個簡單的聯系人的拓展程序(下面會介紹),所以我們呈現該窗體區域的消息類選擇Contact。

  設置完成點擊Finish窗體區域就會成功添加。這時會出現一個自定義控件,我們可以設置里面的控件和樣式。

  

  現在介紹一下我們的拓展程序。這里我們是做一個跟聯系人有關的拓展程序:為聯系人添加附加屬性。我們知道聯系人默認的屬性是有限的,為了方便用戶自定義屬性,Outlook為我們設置了UserProperties方便用戶設置各種自定義屬性。這里我們就要  用它設置我們的定制項。這里我們幫聯系人添加父母及其生日的附加屬性。為簡單起見我們需要兩個textBox和兩個DataTimePicker。布局完成如下:

  

  4.接下來,我們需要處理拓展程序的邏輯部分。主要思路是定義自定義屬性、綁定屬性、屬性變更處理。主要代碼及注釋如下:

View Code
  1         // 自定義的屬性名字
  2         private const string PROPERTY_NAME_MOTHER_NAME = "PROPERTY NAME MOTHER NAME";
  3         private const string PROPERTY_NAME_MOTHER_BIRTHDAY = "PROPERTY NAME MOTHER BIRTHDAY";
  4         private const string PROPERTY_NAME_FATHER_NAME = "PROPERTY NAME FATHER NAME";
  5         private const string PROPERTY_NAME_FATHER_BIRTHDAY = "PROPERTY NAME FATHER BIRTHDAY";
  6 
  7         // 自定義屬性對象
  8         private Outlook.UserProperty _MotherNameProperty = null;
  9         private Outlook.UserProperty _MotherBirthdayProperty = null;
 10         private Outlook.UserProperty _FatherNameProperty = null;
 11         private Outlook.UserProperty _FatherBirthdayProperty = null;
 12 
 13         // 對應的Contact對象
 14         public Outlook.ContactItem _Contact = null;
 15 
 16         // 標記是否內容修改
 17         private bool _Changed = false;
 18 
 19         // Occurs before the form region is displayed.
 20         // Use this.OutlookItem to get a reference to the current Outlook item.
 21         // Use this.OutlookFormRegion to get a reference to the form region.
 22         private void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
 23         {
 24             // 獲得FormRegion所對應的Contact對象
 25             _Contact = ((Microsoft.Office.Tools.Outlook.FormRegionControl)sender).OutlookItem as Outlook.ContactItem;
 26             //_Contact = Globals.ThisAddIn.Application.ActiveInspector().CurrentItem;
 27 
 28             // 從聯系人的自定義屬性中,獲得母親姓名屬性
 29             _MotherNameProperty = _Contact.UserProperties.Find(PROPERTY_NAME_MOTHER_NAME, Type.Missing);
 30             if (_MotherNameProperty != null)
 31             {
 32                 // 如果存在這個屬性,則取出Value為控件賦值
 33                 tbMotherName.Text = _MotherNameProperty.Value as String;
 34             }
 35             else
 36             {
 37                 // 不存在則創建這個屬性
 38                 _MotherNameProperty = _Contact.UserProperties.Add(PROPERTY_NAME_MOTHER_NAME, Outlook.OlUserPropertyType.olText, Type.Missing, Type.Missing);
 39             }
 40 
 41             // 母親生日,原理相同
 42             _MotherBirthdayProperty = _Contact.UserProperties.Find(PROPERTY_NAME_MOTHER_BIRTHDAY, Type.Missing);
 43             if (_MotherBirthdayProperty != null)
 44             {
 45                 dtpMotherBirthday.Value = (DateTime)_MotherBirthdayProperty.Value;
 46             }
 47             else
 48             {
 49                 _MotherBirthdayProperty = _Contact.UserProperties.Add(PROPERTY_NAME_MOTHER_BIRTHDAY, Outlook.OlUserPropertyType.olDateTime, Type.Missing, Type.Missing);
 50             }
 51 
 52             // 父親姓名
 53             _FatherNameProperty = _Contact.UserProperties.Find(PROPERTY_NAME_FATHER_NAME, Type.Missing);
 54             if (_FatherNameProperty != null)
 55             {
 56                 tbFatherName.Text = _FatherNameProperty.Value as String;
 57             }
 58             else
 59             {
 60                 _FatherNameProperty = _Contact.UserProperties.Add(PROPERTY_NAME_FATHER_NAME, Outlook.OlUserPropertyType.olText, Type.Missing, Type.Missing);
 61             }
 62 
 63             // 父親生日
 64             _FatherBirthdayProperty = _Contact.UserProperties.Find(PROPERTY_NAME_FATHER_BIRTHDAY, Type.Missing);
 65             if (_FatherBirthdayProperty != null)
 66             {
 67                 dtpFatherBirthday.Value = (DateTime)_FatherBirthdayProperty.Value;
 68             }
 69             else
 70             {
 71                 _FatherBirthdayProperty = _Contact.UserProperties.Add(PROPERTY_NAME_FATHER_BIRTHDAY, Outlook.OlUserPropertyType.olDateTime, Type.Missing, Type.Missing);
 72             }
 73 
 74             // 將這四個控件綁定change事件,只有在修改之后,我們才會將值回寫到Contact對應的屬性中去
 75             tbMotherName.TextChanged += new EventHandler(content_Changed);
 76             dtpMotherBirthday.ValueChanged += new EventHandler(content_Changed);
 77             tbFatherName.TextChanged += new EventHandler(content_Changed);
 78             dtpFatherBirthday.ValueChanged += new EventHandler(content_Changed);
 79 
 80             // 在Write事件中,把修改的值保存到屬性中去
 81             _Contact.Write += new Microsoft.Office.Interop.Outlook.ItemEvents_10_WriteEventHandler(contact_Write);
 82         }
 83 
 84         void content_Changed(object sender, EventArgs e)
 85         {
 86             // 有修改時,將_Change置為true
 87             _Changed = true;
 88         }
 89 
 90         void contact_Write(ref bool Cancel)
 91         {
 92             if (_Changed)
 93             {
 94                 // 保存值到屬性中去
 95                 _MotherNameProperty.Value = tbMotherName.Text.Trim();
 96                 _MotherBirthdayProperty.Value = dtpMotherBirthday.Value;
 97                 _FatherNameProperty.Value = tbFatherName.Text.Trim();
 98                 _FatherBirthdayProperty.Value = dtpFatherBirthday.Value;
 99             }
100 
101         }
102 
103         // Occurs when the form region is closed.
104         // Use this.OutlookItem to get a reference to the current Outlook item.
105         // Use this.OutlookFormRegion to get a reference to the form region.
106         private void FormRegion1_FormRegionClosed(object sender, System.EventArgs e)
107         {
108             // 關閉事件綁定
109             _Contact.Write -= new Microsoft.Office.Interop.Outlook.ItemEvents_10_WriteEventHandler(contact_Write);
110 
111             // 釋放對象
112             System.Runtime.InteropServices.Marshal.ReleaseComObject(_Contact);
113             _Contact = null;
114         }

  

  現在,拓展程序已經可以調試了。運行后outlook程序會自動啟動並加載此拓展項。打開聯系人信息工作區會看到剛才的窗體區域被成功地加了進去。

  

  

  好了。我們聯系人的自定義屬性已經做好了。為了實例的完整性,現在我們再加一個ribbon控件,使其附加在本地outlook的ribbon菜單項內。其功能為:一.顯示聯系人信息(主要是我們剛才添加的附加屬性信息);二.拓展程序卸載/禁用。

  5添加ribbon:右擊工程名->Add->New Item->Ribbon (Visual Designer).點擊確認后會看到一個ribbon控件被添加了進來。值得注意的是RibbonType屬性,它決定着ribbon的顯示位置默認為Mail.Read。由於我們要將該ribbon顯示在主窗體的  ribbon項集中,因此其RibbonType應勾選Explore(同理如何想讓該ribbon顯示在聯系人窗體的ribbon項中可勾選Contact)。現在我們要為其添加兩個RibbonButton:分別為Show Contacts Info和Unistall。

  

  6.針對Show Contacts Info為了顯示聯系人信息,我們需要添加一個窗體來進行顯示。於是我們可以添加一個UserControl名為ContactsInfoDisplay,其形式如下:

  

  為了顯示聯系人信息,我們可以傳入一個ContactItem作為其構造函數的參數。然后獲取其對象中的相關屬性。代碼如下: 

View Code
 1 public ContactsInfoDisplay(Microsoft.Office.Interop.Outlook.ContactItem contact)
 2         {
 3             InitializeComponent();
 4             this.name.Text = contact.LastName+" "+contact.FirstName;
 5             this.phone.Text = contact.MobileTelephoneNumber;
 6             this.email.Text = contact.Email1Address;
 7             //獲取自定義屬性
 8          this.father.Text = string.Format("{0}({1})", contact.UserProperties.Find("PROPERTY NAME FATHER NAME").Value, contact.UserProperties.Find("PROPERTY NAME FATHER BIRTHDAY").Value);
 9             this.mother.Text = string.Format("{0}({1})", contact.UserProperties.Find("PROPERTY NAME MOTHER NAME").Value, contact.UserProperties.Find("PROPERTY NAME MOTHER BIRTHDAY").Value);
10         }

  7.針對Unistall,我們有兩種策略(第一部分提到)。

         一:刪除注冊表:第一部分提到過outlook加載插件時先檢查注冊表里的特定目錄下的項。如果刪除該項,outlook就不會檢測到從而也就不會加載。代碼如下:

View Code
 1 RegistryKey regKey = null;
 2             RegistryKey regSubKey = null;
 3             try
 4             {
 5                 //Read the key 
 6                 regKey = Microsoft.Win32.Registry.CurrentUser;
 7                 //獲取outlook插件目錄下的子鍵
 8                 regSubKey = regKey.OpenSubKey(string.Format(@"Software\Microsoft\Office\Outlook\Addins"), true);
 9                 //獲取當前插件名
10                 regSubKey.DeleteSubKey(Assembly.GetExecutingAssembly().GetName().Name);
11                 System.Windows.Forms.MessageBox.Show("插件卸載成功,下次啟動生效!");
12             }
13             catch (Exception e)
14             {
15                 System.Windows.Forms.MessageBox.Show(e.Message);
16             }

   二:禁用插件:由於第一種方法只是處理注冊表,因此卸載的不是很徹底。還有很多遺留項。因此推薦使用第二種方法。使outlook將插件禁用,但保留在加載項欄中。想重用時可以手動啟用。其相應的代碼也很簡單。

View Code
1             Microsoft.Office.Core.COMAddIn addin= Globals.ThisAddIn.Application.COMAddIns.Item("OutlookAddInDemo");
2             addin.Connect = false; 

  

  到現在我們的實例已經完整的介紹完了,運行結果如圖。完整工程源代碼下載:http://files.cnblogs.com/maxliu/OutlookAddInDemo.rar

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM