Reputation: 687
I have a control which I can drop mail items on, works fine but I can't get it to clear the selection / items.
For example:
I drag and drop mail 1 --> mail 1 is in my list
I delete mail 1 from my list go back to Outlook and drag and drop mail 2
Mail 2 appears in my list but mail 1 is also revived!
I've found a lot of postings about Marshal.ReleaseComObject
but I guess I'm not doing it in the right way?
Specs: VS2010, 4.0 framework. Windows 7 OS, Outlook 2010
Here's part of my code:
The call to my Save
method:
ElseIf e.Data.GetDataPresent("FileGroupDescriptor") Then
Try
Dim SafeSaveMethod As New dlgCallSaveMails(AddressOf SaveMailsFromSelection)
Me.BeginInvoke(SafeSaveMethod, Me.FileData.Pad)
The Save
method:
Private Sub SaveMailsFromSelection(_path As String)
' File uit Outlook
Dim x As Integer
Dim xitmndx As Integer = 0
Dim DestFile As String
Dim oOutLook As New Outlook.Application
Dim oExplorer As Outlook.Explorer
Dim oSelection As Outlook.Selection
Dim strFile As String
oExplorer = oOutLook.ActiveExplorer
oSelection = oExplorer.Selection
Dim currentFolder As MAPIFolder = oExplorer.CurrentFolder
Dim folders As Folders = currentFolder.Folders
Try
For Each mitem As Object In oSelection
xitmndx += 1
Dim mi As Microsoft.Office.Interop.Outlook.MailItem = TryCast(mitem, Microsoft.Office.Interop.Outlook.MailItem)
mi.SaveAs(_path & "\" & String.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", mi.CreationTime) & "-" & CleanInput(mi.Subject) & ".msg", Outlook.OlSaveAsType.olMSG)
Marshal.ReleaseComObject(mi)
mi = Nothing
Next
Catch ex As System.Exception
WriteError2EventLog("Error picDropZone_DragDrop 4: " & ex.ToString)
MsgBox(Err.Description, MsgBoxStyle.Exclamation, "mycontrol")
Finally
Marshal.ReleaseComObject(oExplorer)
Marshal.ReleaseComObject(oSelection)
Marshal.ReleaseComObject(currentFolder)
Marshal.ReleaseComObject(folders)
Marshal.FinalReleaseComObject(oExplorer)
End Try
End Sub
I also tried oExplorer.ClearSelection()
but as I can tell from the count property it doesn't clear at all
Upvotes: 4
Views: 1750
Reputation: 76
After spending hours reading up on different solutions to this problem, which ends up beeing a bug in Outlooks way of handling the enter-event when moving over a control that can handle drag & drop in another program, I found out that you can fix it with one single line of code and that is something that should be spread!
Microsoft uses the clipboard to store, among other things, information about the selection. The class that is used by Outlook for this purpose is hidden behind the key named RenPrivateMessages. It can't be used because they won't release the interface, but by reading it you clear the lock on the selection.
So, all you have to do in the drop-event in your code is to add this row (given that your EventArg is named e):
e.data.GetData("RenPrivateMessages");
Upvotes: 6
Reputation: 11
I was searching the web for a solution without the workaround to switch the panes. After I had found a solution that worked for me, I would like to share it here.
The final clue, was to use the RemoveFromSelection method of the active explorer, cos the Marshal.ReleaseComObject only don't clear the selection.
Public Sub outlook_drop()
Try
get_outlook_application_explorer()
If IsNothing(oExplorer) = True Then
MessageBox.Show("Cannot open Outlook.")
Exit Sub
End If
Dim selection As Selection = oExplorer.Selection
If selection.Count = 0 Then
Marshal.ReleaseComObject(selection)
MessageBox.Show("Nothing selected.")
Exit Sub
End If
Dim filename As String
Dim ext As String = ".msg"
Dim mail As MailItem ' Important, no 'Shadow'-objects, such as "For Each mail as MailItem in selection", cos you need to free it with Marshal.ReleaseComObject()...
For Each mail In selection
Dim subtxt As String = mail.Subject
If Not String.IsNullOrEmpty(subtxt) Then
If subtxt.Length > 120 Then
subtxt = Left(subtxt, 120)
End If
End If
filename = fill_filename(mail.Attachments.Count.ToString, subtxt, mail.SenderName, mail.ReceivedTime.ToShortDateString)
Dim newFile As String = IO.Path.Combine(fuldir, filename + ext)
Dim count As Integer = 0
While IO.File.Exists(newFile)
count += 1
If count > 25 Then
newFile = Nothing
Exit While
End If
newFile = IO.Path.Combine(fuldir, filename + "(" + count.ToString + ")" + ext)
End While
If String.IsNullOrEmpty(newFile) = False Then
mail.SaveAs(newFile)
End If
oExplorer.RemoveFromSelection(mail) ' Important, to remove the object from Selection, ReleaseComObject() only don't do.
Marshal.ReleaseComObject(mail)
Next
Marshal.ReleaseComObject(selection)
Catch ex As System.Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Regards,
Cali
Upvotes: 1
Reputation: 687
Using a delegate wasn't such a good idea, turns out you can do a workaround to reactivate your outlook.
After saving the mailitem to file I make a call to SwitchOutlookPanes()
Public Sub SwitchOutlookPanes()
Dim Outlook As Microsoft.Office.Interop.Outlook.Application
Dim explorer As Microsoft.Office.Interop.Outlook.Explorer = Nothing
Try
If Outlook Is Nothing Then
If Outlook Is Nothing Then Outlook = CType(Microsoft.VisualBasic.Interaction.GetObject("", "Outlook.Application"), Microsoft.Office.Interop.Outlook.Application)
explorer = Outlook.ActiveExplorer
End If
If Outlook IsNot Nothing And explorer IsNot Nothing Then
Dim nMAPIFOlder As Interop.Outlook.MAPIFolder = explorer.CurrentFolder
explorer.CurrentFolder = Outlook.OlDefaultFolders.olFolderContacts
System.Threading.Thread.Sleep(1500)
explorer.CurrentFolder = nMAPIFOlder
End If
Catch ex As System.Exception
Finally
Marshal.ReleaseComObject(explorer)
Marshal.ReleaseComObject(Outlook)
End Try
End Sub
This clears the selection and prevents Outlook from freezing / hanging..
Regards,
Mike
Upvotes: 0