Drag'n'drop одна или несколько писем из приложения Outlook в С# WPF
Я работаю над клиентом Windows, написанным в WPF с С# на .Net 3.5 Sp1, где требование заключается в том, что данные из писем, полученных клиентами, могут храниться в базе данных. В настоящее время самый простой способ справиться с этим - скопировать и вставить текст, тему, информацию о контакте и время, полученные вручную, с использованием величины ctrl-c/ctrl-v, вызывающей артрит.
Я думал, что простой способ справиться с этим - позволить пользователю перетащить одно или несколько писем из Outlook (все они используют Outlook 2007 в настоящее время) в окно, что позволяет моему приложению извлекать необходимую информацию и отправлять ее к серверной системе для хранения.
Тем не менее, несколько часов поискового запроса информации об этом, похоже, указывают на шокирующее отсутствие информации об этой, казалось бы, основной задаче. Я бы подумал, что что-то вроде этого будет полезно в самых разных настройках, но все, что мне удалось найти, - это полупеченные не-решения.
Есть ли у кого-нибудь советы о том, как это сделать? Поскольку я просто собираюсь читать письма и не посылать ничего или делать что-либо злое, было бы неплохо с решением, которое не включало бы ненавистные всплывающие всплывающие окна безопасности, но что-либо бьется, не имея возможности сделать это вообще.
В принципе, если бы я мог получить список всех почтовых элементов, которые были выбраны, перетаскиваемые из Outlook, я сам смогу справиться с остальными!
Спасибо!
руна
Ответы
Ответ 1
Я нашел отличную статью которая должна делать именно то, что вам нужно.
UPDATE
Мне удалось получить код в этой статье, работающий в WPF с небольшой настройкой, ниже приведены изменения, которые вам нужно сделать.
Измените все ссылки из System.Windows.Forms.IDataObject на System.Windows.IDataObject
В конструкторе OutlookDataObject измените
FieldInfo innerDataField = this.underlyingDataObject.GetType().GetField("innerData", BindingFlags.NonPublic | BindingFlags.Instance);
Для
FieldInfo innerDataField = this.underlyingDataObject.GetType().GetField("_innerData", BindingFlags.NonPublic | BindingFlags.Instance);
Измените все вызовы DataFormats.GetFormat на DataFormats.GetDataFormat
Измените реализацию SetData из
public void SetData(string format, bool autoConvert, object data)
{
this.underlyingDataObject.SetData(format, autoConvert, data);
}
К
public void SetData(string format, object data, bool autoConvert)
{
this.underlyingDataObject.SetData(format, data, autoConvert);
}
С этими изменениями я смог получить это, чтобы сохранить сообщения в файлах, как это сделала статья. Извините за форматирование, но нумерованные/маркированные списки не очень хорошо работают с фрагментами кода.
Ответ 2
Я нашел много решений, предлагающих использовать "FileGroupDescriptor" для всех имен файлов и "FileContents" объекта DragEventArgs для извлечения данных каждого файла. "FileGroupDescriptor" отлично работает для имен сообщений электронной почты, но "FileContents" возвращает нуль, поскольку реализация IDataObject в .NET не может обрабатывать объект IStorage, который возвращается COM.
У Дэвида Эвена есть отличное объяснение, отличная загрузка кода и кода, которая отлично работает на http://www.codeproject.com/KB/office/outlook_drag_drop_in_cs.aspx.
Ответ 3
В вашем Xaml вам нужно настроить свое событие:
<TextBlock
Name="myTextBlock"
Text="Drag something into here"
AllowDrop="True"
DragDrop.Drop="myTextBlock_Drop"
/>
После того, как вы установили AllowDrop = True и установите событие drop, перейдите к коду и настройте свое событие:
private void myTextBlock_Drop(object sender, DragEventArgs e)
{
// Mark the event as handled, so TextBox native Drop handler is not called.
e.Handled = true;
Stream sr;
//Explorer
if (e.Data.GetDataPresent(DataFormats.FileDrop, true))
//Do somthing
//Email Message Subject
if (e.Data.GetDataPresent("FileGroupDescriptor"))
{
sr = e.Data.GetData("FileGroupDescriptor") as Stream;
StreamReader sr = new StreamReader(sr2);//new StreamReader(strPath, Encoding.Default);
//Message Subject
string strFullString = sr.ReadToEnd();
}
}
Если вы хотите разбить его дальше, вы можете использовать:
FILEDESCRIPTOR или FILECONTENTS в следующем виде статья
ваш другой вариант - связать в Outlook MS Office Primary Interop Assemblies и разбить сообщение таким образом.
Ответ 4
Я думаю, Shell Style Drag and Drop в .NET(WPF и WinForms) может вам помочь. Как только вы сможете ответить на перетаскивание с помощью COM-интерфейсов, вы сможете получить данные из Outlook.
Ответ 5
Я предполагаю, что у вас есть сервер Exchange, работающий за Outlook.
Что вы можете сделать, так это получить почту с сервера Exchange и сохранить ее местоположение в базе данных на основе почтовых EntryID
и StoreID
. Вот фрагмент VB.Net:
Imports Microsoft.Office.Interop
Public Class OutlookClientHandler
Private _application As Outlook.Application
Private _namespace As Outlook.NameSpace
Public Sub New()
If Process.GetProcessesByName("outlook".ToLower).Length > 0 Then
_application = New Outlook.Application
Else
Dim startInfo As ProcessStartInfo = New ProcessStartInfo("outlook.exe")
startInfo.WindowStyle = ProcessWindowStyle.Minimized
Process.Start(startInfo)
_application = New Outlook.Application
End If
End Sub
' Retrieves the specified e-mail from Outlook/Exchange via the MAPI
Public Function GetMailItem(ByVal entryID as String, ByVal storeID as String) As Outlook.MailItem
_namespace = _application.GetNamespace("MAPI")
Dim item As Outlook.MailItem
Try
item = _namespace.GetItemFromID(entryID, storeID)
Catch comex As COMException
item = Nothing ' Fugly, e-mail wasn't found!
End Try
Return item
End Function
End Class
Я думаю, вам удобно использовать MAPI, иначе вы можете прочитать здесь:
http://msdn.microsoft.com/en-us/library/cc765775(v=office.12).aspx
Чтобы получить выбранные сообщения электронной почты из Outlook:
Public Function GetSelectedItems() As List(Of Object)
Dim items As List(Of Object) = New List(Of Object)
For Each item As Object In _application.ActiveExplorer().Selection
items.Add(item)
Next
Return items
End Function
После того, как вы получили электронные письма из Outlook, вы можете просто вставить их в свою базу данных! Сохраните их EntryID
и StoreID
(вы можете захотеть сохранить их родительский (папка) EntryID
и StoreID
, а также).