Как получить данные Outlook 2003 в приложении Silverlight 4
-
29-09-2019 - |
Вопрос
Можно ли использовать Automation for Outlook 2003 с Silverlight 4?Или, может быть, есть другой способ использования Outlook 2003 MAPI в приложении Silverlight?
Я использую Silverlight 4 и пытаюсь взаимодействовать с Outlook следующим образом:
dynamic outlook = AutomationFactory.GetObject("Outlook.Application");
В Outlook 2007/2010 все работает нормально.
Но когда я пытаюсь использовать любое поле динамического экземпляра (например, Outlook.Session) из Outlook 2003, я получаю NotSupportedException.Это проблема только Outlook 2003.
Я нашел статью http://msdn.microsoft.com/en-us/library/aa159619%28office.11%29.aspx но для приложения Silverlight это бесполезно (невозможно получить ссылку на офисную сборку или COM напрямую).
Type.GetTypeFromProgID
тоже бесполезно, Silverlight его не поддерживает.
Решение
Я наконец нашел ответ.Большинство действий можно выполнить с использованием стандартной объектной модели Outlook 2003.Все эти действия описаны в эта статья Microsoft.Основное различие между примерами в статье и кодом 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 не нужно запускать).