Spellcheck throws System.AccessViolationException

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

Spellcheck throws System.AccessViolationException
 
German Hayles




Posts: 41
Joined: 2015-04-27
OFFICE 365 / VS2022 / Outlook Version 2212 Build 15928.20282

Whenever a spellcheck is done I get a System.AccessViolationException.

PRE-CONDITION:
Have COM Add-In that overrides InspectorActivate event.

RECREATE STEPS
Open a new email item
Type in a few words and misspell one of them.
Left Mouse click on the word and select one of the choices given.
Click on your choice
Exception is thrown

What happens is that after the user selects a word from the drop down list presented by the Spellchecker, the InpsectorActivate event is fired.

Inside of the event handler, I read the body of the message looking for a particular url.

The problem is that this line of code will throw the exception:

if (mailItem.Body == null)

That line is executed many times without a problem; unless it is reached after a Spellcheck
Posted 15 Mar, 2023 21:33:37 Top
Andrei Smolin


Add-in Express team


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

This looks like an issue in the Outlook object model. I suggest that introduce a small delay before executing the logic which is now written in InspectorActivate. To achieve this, use the SendMessage/OnSendMessage machinery that we describe in section Wait a little; see the PDF file in the folder {Add-in Express}\Docs on your development PC. When the OnSendMessage event occurs and you filter out your message, get ActiveInspector and execute your logic for that Inspector object.

Regards from Poland (GMT+1),

Andrei Smolin
Add-in Express Team Leader
Posted 16 Mar, 2023 05:04:46 Top
German Hayles




Posts: 41
Joined: 2015-04-27
Hello Andrei,

Firstly, thanks for the SendMessage/OnSendMessage tip. That will come in very useful.

Your instinct about the Outlook Object Model was right. It turns out that the object being sent to my "InspectorActivate" is NOT an Outlook._MailItem as I'd originally thought. This code has been running in place for literally years now; it's only been failing recently. I used similar code to what I'm showing below to resolve the issue.

Below is a sample piece of code I'm using to detect whether or not I'm being sent a _MailItem object.


        private void adxOutlookAppEvents1_InspectorActivate(object sender, object inspector, string folderName)
        {
            if( inspector.GetType() == typeof(Outlook._MailItem ) ) 
            {
                System.Diagnostics.Debug.WriteLine("Inspector is a mail Item");
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Inspector is NOT a mail Item");
            }
        }
Posted 20 Mar, 2023 08:24:44 Top
Andrei Smolin


Add-in Express team


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

German Hayles writes:
the object being sent to my "InspectorActivate" is NOT an Outlook._MailItem


The inspector parameter should be cast to Outlook.Inspector. To retrieve the MailItem, use Inspector.CurrentItem.

Regards from Poland (GMT+1),

Andrei Smolin
Add-in Express Team Leader
Posted 20 Mar, 2023 09:03:23 Top
German Hayles




Posts: 41
Joined: 2015-04-27
As usual, you're right.

I noticed that shortly after I sent my message. The code below shows what I eventually did.

NOW IT GETS WEIRD
When I ran this, I noticed that the same null access violation was being thrown. However, I had a break point on that piece of code because I wanted to see what was inside the object.

At first, you could see that HTMLBody was throwing an exception. I had to move away from the screen for a few minutes and when I got back, I noticed that the HTMLBody was populated with data!!!

Like you said, WAITING may be what i need to do. I'll get back to you to confirm.



private void adxOutlookAppEvents1_InspectorActivate(object sender, object inspector, string folderName)
        {
            var thisInspector = inspector as Outlook._Inspector;
            Outlook._MailItem mi = null;

            try
            {
                var inspectorType = thisInspector.CurrentItem.GetType().InvokeMember("Class", BindingFlags.GetProperty, null, thisInspector.CurrentItem, null);

                switch ((OlObjectClass)inspectorType)
                {
                    case OlObjectClass.olMail:
                        mi = thisInspector.CurrentItem as Outlook.MailItem;
                        if (mi != null)
                        {
                            System.Diagnostics.Debug.Write(mi.HTMLBody);
                        }
                        break;
                    case OlObjectClass.olAppointment:
                        break;
                    default:
                        break;

                }
                System.Diagnostics.Debug.Write(inspectorType.ToString());
            }

            catch (System.Exception  ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }
    }
Posted 20 Mar, 2023 11:02:40 Top
German Hayles




Posts: 41
Joined: 2015-04-27
FINAL FORM, I HOPE






...
        private const int WM_USER = 0x0400; 
        private const int MYMESSAGE = WM_USER + 1000;
...
        private void adxOutlookAppEvents1_InspectorActivate(object sender, object inspector, string folderName)
        {
            var thisInspector = inspector as Outlook._Inspector;
            

            try
            {
                var inspectorType = thisInspector.CurrentItem.GetType().InvokeMember("Class", BindingFlags.GetProperty, null, thisInspector.CurrentItem, null);

                switch ((OlObjectClass)inspectorType)
                {
                    case OlObjectClass.olMail:
                        this.SendMessage(MYMESSAGE, (IntPtr)0, (IntPtr)GCHandle.Alloc(inspector) );
                        break;
                    case OlObjectClass.olAppointment:
                        break;
                    default:
                        break;

                }
                System.Diagnostics.Debug.Write(inspectorType.ToString());
            }

            catch (System.Exception  ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }

        private void AddinModule_OnSendMessage(object sender, ADXSendMessageEventArgs e)
        {
            GCHandle inspectorHandle = (GCHandle)e.LParam;

            var inspector = inspectorHandle.Target as Outlook._Inspector;

            var mi = inspector.CurrentItem as Outlook.MailItem;
            if (mi != null)
            {
                System.Diagnostics.Debug.Write(mi.HTMLBody);
            }
        }
Posted 20 Mar, 2023 12:48:55 Top
Andrei Smolin


Add-in Express team


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

In AddinModule_OnSendMessage you *must* check whether you get e.Message equal to MYMESSAGE before you do anything. There are a lot of messages that this event handler receives.

Regards from Poland (GMT+1),

Andrei Smolin
Add-in Express Team Leader
Posted 20 Mar, 2023 14:29:14 Top
German Hayles




Posts: 41
Joined: 2015-04-27
Thanks.

I updated it, and it's working fine now.

Thanks AGAIN, Andrei
Posted 20 Mar, 2023 16:55:07 Top
Andrei Smolin


Add-in Express team


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

Regards from Poland (GMT+1),

Andrei Smolin
Add-in Express Team Leader
Posted 21 Mar, 2023 03:33:43 Top