2010-06-25 102 views
0

可以在Silverlight 4中使用Automation for Outlook 2003嗎?或者在Silverlight應用程序中使用Outlook 2003 MAPI有一些不同的方法?如何在Silverlight 4應用程序中獲取Outlook 2003數據

我使用Silverlight 4中,我試圖與Outlook以這種方式互動:

dynamic outlook = AutomationFactory.GetObject("Outlook.Application"); 

對於Outlook 2007/2010一切工作正常。

但是,當我嘗試從Outlook 2003使用動態實例(例如outlook.Session)的任何領域,然後我得到NotSupportedException。這只是Outlook 2003的問題。

我發現文章http://msdn.microsoft.com/en-us/library/aa159619%28office.11%29.aspx,但它對Silverlight應用程序沒用(不可能直接獲得office組件或COM的引用)。

Type.GetTypeFromProgID也沒用,Silverlight不支持它。

回答

1

我終於找到了答案。 大部分操作都可以使用標準Outlook 2003對象模型執行。所有這些操作在this Microsoft article中描述。 文章和Silverlight代碼中的示例之間的主要區別 - 我們無法引用Interop Outlook程序集,因此我們需要使用動態。 因此,從聯繫人列表或所有收件箱電子郵件中獲取所有聯繫人非常容易(請參閱文章)。最困難的部分是獲取創建的用戶帳戶列表。 Outlook 2003的對象模型提供了可能獲得唯一一個(默認)帳戶:

dynamic outlook = AutomationFactory.CreateObject("Outlook.Application"); 
var ns = outlook.GetNamespace("MAPI"); 
var defaultAccount = ns.CurrentUser; 

但它仍然是不適合我。這非常可悲,但是Outlook 2003對象模型中沒有Session.Accounts屬性。所以我發現只有一個棘手的方法來獲取帳戶列表。

public class Ol11ImportStrategy 
    { 
     const string registryPath = @"HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\{0}\{1}"; 
     const string constAccountName = "Account Name"; 
     const string constEmail = "Email"; 
     const string constSMTPServer = "SMTP Server"; 
     const string constName = "Display Name"; 
     const string constIMAPServer = "IMAP Server"; 
     const string constPOP3Server = "POP3 Server"; 
     const string constValueClsid = "clsid"; 
     const string constContentsAccountClsid_POP3 = "{ED475411-B0D6-11D2-8C3B-00104B2A6676}"; 
     const string constContentsAccountClsid_IMAP = "{ED475412-B0D6-11D2-8C3B-00104B2A6676}"; 

     public IEnumerable<AccountEntity> GetAccountsInFriendlyFormat() 
     { 
      List<AccountEntity> accounts = new List<AccountEntity>(); 

      using (dynamic WShell = AutomationFactory.CreateObject("WScript.Shell")) 
      { 
       for (int i = 1; i < 1000; i++) 
       { 
        try 
        { 
         string classId = WShell.RegRead(String.Format(registryPath, i.ToString().PadLeft(8, '0'), constValueClsid)); 

         if (StringComparer.InvariantCultureIgnoreCase.Compare(classId, constContentsAccountClsid_POP3) == 0) 
         { 
          accounts.Add(new AccountEntity 
          { 
           FriendlyName = GetRegisterElementValue(WShell, i.ToString(), constAccountName), 
           IncomingMailServer = GetRegisterElementValue(WShell, i.ToString(), constPOP3Server), 
           Email = GetRegisterElementValue(WShell, i.ToString(), constEmail), 
           UserName = GetRegisterElementValue(WShell, i.ToString(), constName) 
          }); 
          continue; 
         } 

         if (StringComparer.InvariantCultureIgnoreCase.Compare(classId, constContentsAccountClsid_IMAP) == 0) 
         { 
          accounts.Add(new AccountEntity 
          { 
           FriendlyName = GetRegisterElementValue(WShell, i.ToString(), constAccountName), 
           IncomingMailServer = GetRegisterElementValue(WShell, i.ToString(), constIMAPServer), 
           Email = GetRegisterElementValue(WShell, i.ToString(), constEmail), 
           UserName = GetRegisterElementValue(WShell, i.ToString(), constName) 
          }); 
          continue; 
         } 

         //it isn't POP3 either IMAP 
        } 
        catch (FileNotFoundException e) 
        { 
         //classId isn't found - we can break iterations because we already iterate through all elements 
         break; 
        } 
        catch (Exception e) 
        { 
         MessageBox.Show("Unknown exception"); 
        } 
       } 
      } 

      return accounts; 
     } 

     private string GetRegisterElementValue(object scriptShell, string elementNumber, string elementName) 
     { 
      dynamic shell = scriptShell; 
      string currentElement = elementNumber.PadLeft(8, '0'); 

      object[] currentElementData = shell.RegRead(String.Format(registryPath, currentElement, elementName)); 

      byte[] dataBytes = currentElementData.Cast<byte>().ToArray(); 
      return Encoding.Unicode.GetString(dataBytes, 0, dataBytes.Count()).Trim('\0'); 
     } 
    } 

public class AccountEntity 
{ 
    public string FriendlyName { get; set; } 
    public string UserName { get; set; } 
    public string Email { get; set; } 
    public string AccountType { get; set; } 
    public string IncomingMailServer { get; set; } 
} 

主要技巧是使用AutomationFactory.CreateObject(「WScript.Shell」)。現在可以使用RegRead方法直接從註冊表獲取帳戶信息。順便說一下,即使對於Outlook 2007/2010,此代碼也能正常工作。而對於我來說,如果帳號應該默默收集(在收集數據之前不需要啓動Outlook),這是最可取的方式。

相關問題