Properties removed from PropertyAccessor sometimes "resurfacing"?

Add-in Express™ Support Service
That's what is more important than anything else

Properties removed from PropertyAccessor sometimes "resurfacing"?
Issue with Sent Items - Outlook 365 - Cached Exchange Mode? 
Pino Carafa




Posts: 162
Joined: 2016-09-28
Ok .... I am going to find it difficult to describe this problem so please bear with me and don't hesitate to ask for clarification.

In our Add-in we process items in the Sent Items folder.

When the user composes an email we use the MailItem's PropertyAccessor to set a few header values. In the Sent Items these are subsequently picked up, and the user is then shown a dialog in which they can make a decision. One of the decisions the user can make is to Cancel out of the dialog, at which point we clear those properties out of the PropertyAccessor and Save the MailItem.

This is where it gets interesting. We look at the Sent Items folder periodically to see whether any recent mails in that folder have such properties in their PropertyAccessor, and if they do we present the user with that dialog.

Users are reporting that sometimes the dialog pops up for a Mail Item that they recently already got the dialog for and that they Canceled out of. So I know that we removed those properties from the PropertyAccessor and Saved the email, so our routine should actually ignore such a Mail Item.

One intriguing thing is that the problem seems to "go away" when the user unchecks Cached Exchange Mode.

So I am wondering whether I am observing an issue here where we do work on a "local" copy of a Mail Item which then somehow gets overwritten by Outlook after retrieving an "original" from the Mail Server and that that causes these Properties to "reappear"? If so... is there anything I can do about this, something to tell Outlook that the "local" version is the most current one and it should take precedence over the "server" version so that if anything gets updated by outlook it should be Local-> Server, not Server -> Local

Am I barking up the right tree?
Posted 25 Sep, 2019 05:13:53 Top
Andrei Smolin


Add-in Express team


Posts: 18793
Joined: 2006-05-11
Hello Pino,

Do you use Items.Restrict to get the items with your property? How do you filter out emails non-processed?


Andrei Smolin
Add-in Express Team Leader
Posted 25 Sep, 2019 06:41:21 Top
Pino Carafa




Posts: 162
Joined: 2016-09-28
Hello Andrei,

No we don't use that.... our approach is probably a lot less elegant. We sort the Sent Items folder by [SentOn] descending and then go through that list until we hit one that is older than a certain number of days and we ignore the rest. For every MailItem we find we check whether it has that property, and if it does, we'll process it.

Now in the meantime I have observed a few interesting things.

When the user hits cancel we remove a few properties from the propertyaccessor and we remove and set a few properties from the .UserProperties and then we perform a .Save() on the MailItem. Stepping through the code I noticed that the .Saved property at the point where we perform .Save() was still True despite us setting and removing these. I tried to "force" it by setting the .Body, .RTFBody c.q. .HTMLBody to itself (depending on the bodyformat) which does flip the value of .Saved back to False alright, and then .Save() it - but it made no change to this behaviour.

I DID however notice something interesting. I added a breakpoint in the code where it tries to reprocess the sent items, and I stopped it from performing this work when it tried to reproces a mailitem out of which I had canceled. When I then opened that mailitem I noticed this at the top:

"This is the most recent version but you have made changes to another copy. Click here to see other versions."

I wonder whether that is what is behind all this, and if so.... what can I do to prevent it?
Posted 26 Sep, 2019 03:57:33 Top
Andrei Smolin


Add-in Express team


Posts: 18793
Joined: 2006-05-11
Hello Pino,

Pino Carafa writes:
Stepping through the code I noticed that the .Saved property at the point where we perform .Save() was still True despite us setting and removing these.


This may be an indication of that item being non released by your add-in; possibly, by some other add-in (turn all of them off) or by another part of your add-in.

You should release every COM object created in your code. You create a COM object by mere calling a property or method returning an object type (not a string, Boolean, number, or enum). OutlookApp.ActiveExplorer().Selection[1] creates these COM objects:

- Outlook.Explorer
- Outlook.Selection
- object containing the currently selected item

Your add-in should release all of them.

In your scenario, you should have that email released by the moment you get it from the folder.

Recommended is: release a COM object as soon as you don't need it. If you need to cache a COM object, cache the information that needed to recreate it; e.g. MailItem.EntryId.

Restrict works faster than sorting. At https://www.add-in-express.com/creating-addins-blog/2011/11/10/outlook-newmail-custom-solution/, we use it in a similar scenario.


Andrei Smolin
Add-in Express Team Leader
Posted 26 Sep, 2019 04:18:24 Top
Pino Carafa




Posts: 162
Joined: 2016-09-28
Thanks Andrei I will look into that situation
Posted 26 Sep, 2019 04:34:36 Top
Andrei Smolin


Add-in Express team


Posts: 18793
Joined: 2006-05-11
You are welcome!


Andrei Smolin
Add-in Express Team Leader
Posted 26 Sep, 2019 04:55:05 Top
Pino Carafa




Posts: 162
Joined: 2016-09-28
Hello Andrei,

Ok I think I have a workable solution now but it's still a bit strange.

I've implemented some of the recommendations you gave me here and this is what I found.

Let's say I have a Shared string variable containing an Entry ID and a Date variable containing the Sent On date. By doing this i can ensure that nothing "outlook" itself is doing could possibly "get in the way". I create a System.Windows.Forms.Timer and when it ticks I look at these variables. The timer "ticks" and at that point I have literally *nothing* other than those two variables. And if I then simply destroy the timer, do nothing, and I look at my sent items I can confirm that no item is showing this "This is the most recent version but you have made changes to another copy" message. So all is well.

Now I have a string containing an Entry ID. I find that I cannot use that in a .Restrict as per:
https://docs.microsoft.com/en-us/office/vba/api/outlook.items.restrict
"This method cannot be used and will cause an error with the following properties" - and EntryID is listed. I can confirm that this does indeed raise an error. That's why I got the Date variable. I use Restrict to find only the items sent on that Date and then go through the few of those to find the item that matches the Entry ID.

Try
oItemsMatch = moSentItems.Restrict(sFilter)
Catch ex As Exception

End Try
If Not oItemsMatch Is Nothing Then
Dim nItems As Integer = oItemsMatch.Count
Dim nItem As Integer = 1
While nItem <= nItems
Try
oItemObject = oItemsMatch.Item(nItem)
Catch

End Try
Try
If oItemObject.EntryID = oItem.EntryID Then
bFound = True
End If
Catch

End Try
If bFound Then
Exit While
End If
Try
Marshal.FinalReleaseComObject(oItemObject)
Catch

End Try
oItemObject = Nothing
nItem = nItem + 1
End While
Try
Marshal.FinalReleaseComObject(oItemsMatch)
Catch

End Try
oItemsMatch = Nothing
End If
End If

If oItemObject is not nothing after this, I get rid of the final reference
Try
Marshal.FinalReleaseComObject(oItemObject)
Catch

End Try

Because I'm doing all this in the "tick" handler of my own timer I am not worried that I may be releasing a handle on anything that Outlook is still using, so this is quite safe.

If I leave it at THIS, I find that the messages are still perfectly fine. None of them show the "This is the most recent version but you have made changes to another copy" message, so all is still well..

(more to follow)
Posted 26 Sep, 2019 09:26:19 Top
Pino Carafa




Posts: 162
Joined: 2016-09-28
I then add another piece of code to get an actual Outlook.Mailitem object:

If Not oItemObject Is Nothing Then
oMailItem = TryCast(oItemObject, Outlook.MailItem)
End If

and then I add code to check a User Property (for this example I used a User Property rather than using the PropertyAccessor)

If Not oMailItem Is Nothing Then
Dim bAlreadyChecked As Boolean = True
Dim oProps As Outlook.UserProperties = Nothing
Try
oProps = oMailItem.UserProperties
Catch

End Try
If oProps.Find("SentItemChecked") Is Nothing Then
oProps.Add("SentItemChecked", Outlook.OlUserPropertyType.olText)
bAlreadyChecked = False
End If
Try
Marshal.FinalReleaseComObject(oProps)
Catch

End Try
oProps = Nothing

If Not bAlreadyChecked Then
oMailItem.Save()
End If
Try
Marshal.FinalReleaseComObject(oMailItem)
Catch

End Try
oMailItem = Nothing
End If


As far as I can tell I'm still releasing everything I need to release but NOW it does show "This is the most recent version but you have made changes to another copy"

I eventually found what seems to be a workable solution. After doing oMailItem.Save I do oMailItem.Copy, then oMailItem.Delete - after releasing the references to the mailitem and its copy I no longer get the "This is the most recent version but you have made changes to another copy" message. But if I'm not releasing what I should be releasing I don't know what....
Posted 26 Sep, 2019 09:32:19 Top
Pino Carafa




Posts: 162
Joined: 2016-09-28
Ahhhhh. wait...... oProps.Add("SentItemChecked", Outlook.OlUserPropertyType.olText)

I bet I need to also release the object *it* returns.
Posted 26 Sep, 2019 09:50:46 Top
Pino Carafa




Posts: 162
Joined: 2016-09-28
Alas that didn't work either .... *but* copying and deleting does. Ah well. It'll have to do. :)
Posted 26 Sep, 2019 09:57:46 Top