|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Hi,
I've got a snippet of code from that's fired when any of the To, Cc, Bcc properties are changed in an outlook item:
Private Function HasExternalRecipients(ByVal recipients As Outlook.Recipients) As Boolean
If recipients.Count Then
For Each recipient As Outlook.Recipient In recipients
Dim entry As Outlook.AddressEntry = recipient.AddressEntry
If entry IsNot Nothing Then
Dim smtpAddress As String = ""
If (entry.Type = "EX") Then
smtpAddress = GetSMTPAddressViaOutlookObjectModel(entry)
Else
smtpAddress = entry.Address
End If
Marshal.ReleaseComObject(entry)
Marshal.ReleaseComObject(recipient)
If IsExternalRecipient(smtpAddress) = True Then
Return True
End If
End If
Next
End If
Return False
End Function
Essentially it checks the recipients of the email to see whether they are external and returns a bool based on this.
The problem I am having at the moment is when opening an email via a mailto link, I then go to remove a recipient and it crashes the whole of outlook with the following item in event viewer:
Faulting application name: OUTLOOK.EXE, version: 16.0.11328.20468, time stamp: 0x5dbb4e2f
Faulting module name: RICHED20.DLL, version: 16.0.11328.20468, time stamp: 0x5dbb4d59
Exception code: 0xc0000005
Fault offset: 0x000a52a0
Faulting process ID: 0x6dfc
Faulting application start time: 0x01d74bcf0aefe66a
Faulting application path: C:Program Files (x86)Microsoft Office
ootOffice16OUTLOOK.EXE
Faulting module path: C:Program Files (x86)Microsoft Office
ootfsProgramFilesCommonX86Microsoft SharedOFFICE16RICHED20.DLL
Report ID: 36cad1e4-e0ef-4879-8110-4e3f88ad3fb1
Faulting package full name:
Faulting package-relative application ID:
Any help with this would be massively appreciated as i've been banging my head against the wall all morning! |
|
Posted 18 May, 2021 06:17:55
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18829
Joined: 2006-05-11
|
Hello Alex,
Check section Wait a little; see the PDF file in the folder {Add-in Express}\Docs on your development PC. Use that approach to create a small delay before deleting the recipient.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 18 May, 2021 06:22:35
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Morning Andrei,
Thanks for the quick reply, I am actually using the GUI to remove a recipient rather than doing it programmatically, is this still the correct approach to take?
If this is the case, am I just going to be listening for a receipient delete event and then using the OnSendMessage approach to delay the actual deletion from occurring? |
|
Posted 19 May, 2021 02:53:15
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18829
Joined: 2006-05-11
|
Hello Alex,
I might misunderstand your description. So, you open an email by clicking a mailto link and then delete a recipient right in the UI, correct?
Note that using a mailto link opens a modal inspector (this is a so-called Simple MAPI inspector). Not sure how this influences the issue though. I don't understand how that code fragment returning a Boolean is invoked and how you process that Boolean.
Also, I'd suggest that you use debug messages to find out when Outlook crashes. Use System.Diagnostics.Debug.Writeline.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 19 May, 2021 03:29:41
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Sorry Andrei, I probably haven't explained myself very well!
Yes I am using a mailto link to simulate opening an email from an external program. When I delete the recipient using the UI this is when outlook crashes.
The above snippet is invoked by using an OutlookItemEvents class, it uses the ProcessPropertyChange method to check whether the To,Cc,Bcc or Subject are changed and then updates my plugins UI accordingly. I wonder whether the application is in the middle of resolving the recipient and that's why it is crashing.
See the ProcessPropertyChange method below:
Public Overrides Sub ProcessPropertyChange(ByVal Name As String)
Dim props() As String = {"TO", "CC", "BCC", "SUBJECT"}
If Name IsNot Nothing And Not String.IsNullOrEmpty(Name) Then
Dim found As String = Array.Find(props, Function(x) (x.Equals(Name.ToUpper)))
If found IsNot Nothing Then
If TypeOf Me.ItemObj Is Outlook._MailItem Then
Dim mailItem As Object = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(Me.ItemObj))
If Not mailItem.Sent Then
am.DoPropertyChange(Name, mailItem)
End If
If mailItem IsNot Nothing Then
Marshal.ReleaseComObject(mailItem)
End If
End If
End If
End If
End Sub
DoPropertyChange method below:
Public Sub DoPropertyChange(ByVal PropName As String, Optional ByVal mail As Outlook.MailItem = Nothing)
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetCurrentForm(), EmailAutoFilingHost)
Dim mailItem As Object = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(mail))
If mailItem IsNot Nothing And form IsNot Nothing Then
Dim shouldFile As Boolean = WillBeFiled(mailItem, form.FileInternal, form.ShouldNotFile)
form.DoBackgroundPaint(shouldFile, OfficeColorScheme)
End If
If PropName.ToUpper = "SUBJECT" Then
Dim Subject As String = mailItem.Subject
Dim Viewable = CasecodeViewableLookup(Subject)
form.OcisViewable = Viewable
End If
If mailItem IsNot Nothing Then
Marshal.ReleaseComObject(mailItem)
End If
End Sub
And finally the WillBeFiled method that calls the HasExtrernalRecipients method:
Public Function WillBeFiled(ByVal mail As Outlook.MailItem, ByVal internalFile As Boolean, ByVal shouldNotFile As Boolean) As Boolean
If mail IsNot Nothing And Not shouldNotFile Then
Dim recipients As Outlook.Recipients = mail.Recipients
If recipients.Count > 0 Then
Dim hasExtRecipients As Boolean = HasExternalRecipients(recipients)
Marshal.ReleaseComObject(recipients)
If (hasExtRecipients Or internalFile) And StringHasCaseCodes(mail.Subject) Then
Return True
End If
End If
End If
Return False
End Function
Apologies for all the code pastes, I know it may be a little difficult to see the wood for the trees! If you'd like I can try and get a demo project together? I will try and stick some debug messages in now to find the exact point of crash. |
|
Posted 19 May, 2021 03:54:45
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
|
Posted 19 May, 2021 07:57:48
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18829
Joined: 2006-05-11
|
Hello Alex,
Thank you for the project.
I've found these issues:
- WillBeFiled leaves the recipients variable unreleased if there's no recipients on the email being opened.
- HasExternalRecipients uses foreach (instead of for) and leaves unreleased 1) recipient, 2) entry.
Check if the above helps. If not, what scenario do you test?
Also, OutlookItemEvents is left connected to an email's events in this scenario: you open the email and close it. I suggest that you use ExplorerActivate to disconnect from events:
If OutlookItemEvents.IsConnected Then
OutlookItemEvents.RemoveConnection()
End If
Andrei Smolin
Add-in Express Team Leader |
|
Posted 20 May, 2021 02:07:26
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Good Afternoon Andrei,
As suggested above, i've made the changes. This doesn't seem to of fixed the crash issue though. Please see an updated link with the latest changes: https://hgfltd-my.sharepoint.com/:u:/g/personal/acarter_hgf_com/EairLMArcWVPstwKTumYHLgBsy0V6IwnGbElMP99Aog1Tg?e=msxCMS
I have actually emailed myself an with a mailto link in to click on for testing. The mailto link is as follows: mailto:alexcarter404@msn.com?cc=john.doe@msn.com&subject=Test%20P100006
If it helps I can forward this to you? Once I click this an email opens, when I remove the recipient it then crashes outlook. |
|
Posted 20 May, 2021 08:00:41
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18829
Joined: 2006-05-11
|
Hello Alex,
Add debug messages to find out how the events work and how all your methods are invokes.
In my tests, the ProcessOpen call (= MailItem.Open event) isn't finished yet when three series of ProcessPropertyChange calls (=MailItem.PropertyChange event) occur: each series handles changes in To, CC, Bcc; I didn't study the actual changes, though. After that the ProcessOpen call completes. I've tried to use a Boolean flag to bypass handling these ProcessPropertyChange calls in this case. This may not be correct though: whether this is so or not depends on the actual changes these three series of ProcessPropertyChange calls perform. Anyway, this didn't help. I would suggest that you try a different approach: do not handle the ProcessOpen call at all.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 21 May, 2021 02:06:24
|
|
Top
|
|