How to Ignore ItemChange Caused by Removing a Reminder

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

How to Ignore ItemChange Caused by Removing a Reminder
 
Joe Acunzo




Posts: 13
Joined: 2012-01-03
I'm trapping ItemChange events to process changes to AppointmentItems and MeetingItems. When the event fires, I prompt the user to update an external database. However, if the change is due to dismissing a reminder, I do not want to prompt the user.

Any thoughts on how to handle this?

I see there is a ReminderRemove event, but the problem is that it fires after the ItemChange event. It also appears that on a recurring item, there is no ReminderRemove event, but instead a ReminderChange event when dismissing the reminder. So would need to distinquish a dismissal of the reminder from someone actually changing the reminder time, which would warrant prompting the user.

Also, I know there is a ADXOutlookItemEvents.ProcessPropertyChange handler, but I'd rather not trap events on all calendar items, and not sure about the timing. That is, will PropertyChange come before, or after ItemChange?

I thought of queuing the ItemChange events and delay processing 500 to 1000 milliseconds to see if a ReminderRemove or ReminderChange event fires. But I'd rather not introduce that type of complexity (i.e. build a queue, have another thread processing the queue, etc.).
Posted 28 Feb, 2019 17:08:30 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
Hello Joe,

Joe Acunzo writes:
Also, I know there is a ADXOutlookItemEvents.ProcessPropertyChange handler, but I'd rather not trap events on all calendar items, and not sure about the timing. That is, will PropertyChange come before, or after ItemChange?


This requires using the Outlook Events Logger add-in to answer this question. Also note that the user may edit an appointment inline: select an appointment and then click it once again.

Joe Acunzo writes:
I thought of queuing the ItemChange events and delay processing 500 to 1000 milliseconds to see if a ReminderRemove or ReminderChange event fires.


This looks too risky for me. I would consider intercepting ReminderRemove and ReminderChange events. In this case, you would need to store some info about reminders so that when ReminderRemove occurs you could scan existing reminders and use the previously stored information to find what reminder was deleted and to what item it related. Well, I don't know if ReminderRemove occurs when the user deletes the item with a reminder on it.

On another note. We met reminders-related issues quite often. If you run into an unaccountable issue, something that only occurs on a given machine, try to run scanpst.exe (if a PST is used) or delete the .ost file; check https://support.office.com/en-us/article/repair-outlook-data-files-pst-and-ost-25663bc3-11ec-4412-86c4-60458afc5253. Also, we had an issue with an add-in from Microsoft; the add-in created a message store and a 30 sec delay occurred when Add-in Express connected to the events of the Reminders collection; the issue was caused by the store not initialized properly or something similar. Recommendation: always turn all other COM add-ins off when checking an issue on the customer's.


Andrei Smolin
Add-in Express Team Leader
Posted 01 Mar, 2019 03:18:10 Top
Joe Acunzo




Posts: 13
Joined: 2012-01-03
Thank you Andrei, but I'm not sure how your suggestion would help. Recall my goal is to detect a dismissal of a reminder, and only that, no other change to the AppointmentItem. Meanwhile, I have an approach, but there is still a problem, and could use some more input. Here's what I've done, and the problem with the approach.

When receiving an ItemChange event, inside that event processing, there is a loop for up to one second, calling System.Windows.Forms.Application.DoEvents() inside the loop to allow events to fire, and also Sleep for 10 ms inside the loop to avoid spiking the CPU. ReminderChange event is trapped, and the time received is saved. Back in the loop inside ItemChange, there is a check for the ReminderChange received, and if seen, the code ignores the ItemChange event (i.e. do not prompt the user to update the external database).

That all works when dismissing a reminder, but now the problem is that when you change an AppointmentItem start time, that causes ReminderChange to fire, which is really too bad. So my code ignores the change to the start time when it should actually be processing this change.

I cannot ConnectTo all AppointmentItems due to too much overhead. For example, on my test machine with my Outlook, I have over 10,000 AppointmentItems (real appointments over 10+ years), and I tried to ConnectTo all of them. It took a couple of minutes, and eventually ran out of memory (with 32 GB of RAM).

So the real issue is how to detect just a dismissal of the reminder, and no other changes to the AppointmentItem without connecting to all of them. More thoughts on how to accomplish this would be most welcome.

Thanks.
Posted 03 Mar, 2019 13:33:40 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
Hello Joe,

What stops you from using the ReminderRemove event?

Joe Acunzo writes:
When receiving an ItemChange event, inside that event processing, there is a loop for up to one second, calling System.Windows.Forms.Application.DoEvents() inside the loop to allow events to fire


Using DoEvents is like opening the door welcoming any kind of disaster. Say, you may get one or more ItemChange while the current ItemChange is waiting. Or, you may get several ItemChange events waiting and then they will become revived in an unpredictable order. There're many pages under the umbrella title "DoEvents is evil"; google for this.

Joe Acunzo writes:
also Sleep for 10 ms inside the loop to avoid spiking the CPU


That would mean stopping the thread in which Outlook works for 10 ms. I wouldn't recommend doing this.


Andrei Smolin
Add-in Express Team Leader
Posted 04 Mar, 2019 06:11:07 Top
Joe Acunzo




Posts: 13
Joined: 2012-01-03
The problem with relying just on ReminderRemove is that it fires after ItemChange, which is too late as I do not want to process if just a dismissal of a reminder. Again, I need to determine if the only change was a dismissal of a reminder.

The other problem with ReminderRemove is that it fires if you edit the appointment and actually remove the reminder, no matter what other changes you might make. So let's say you change the Subject and remove the reminder. I want to process the item in this case because of the Subject change.

I have another approach I'm still testing that seems to be working. This new approach doesn't require the use of the "evil" DoEvents! Here's what I'm doing. On ExplorerSelectionChange and on NewInspector, I connect to events for the item. I trap ProcessWrite and make note of the time. I also trap BeforeMoveItem because you can move an appointment without selecting it, so events are not trapped. Then when an ItemChange occurs, if it's an AppointmentItem, but there was not a recent BeforeMoveItem or ProcessWrite event seen, it's inferred to be just a dismissal of a reminder.

Can you think of any problems with this approach?
Posted 04 Mar, 2019 16:45:30 Top
Dmitry Kostochko


Add-in Express team


Posts: 2875
Joined: 2004-04-05
Hi Joe,

Thank you for the detailed description.

Your solution with ProcessWrite seems working but I would suggest you carefully test it against all supported Outlook versions.
Posted 05 Mar, 2019 08:40:44 Top