none
Outlook 2010 : Microsoft Word : Save and Send

    Question

  • Hello All! I have an outlook add-in that adds a ribbon togglebutton to TabNewMailMessage.

    The togglebutton lets you toggle a CustomTaskPane's visibility in the email composing window.

    I notice that if you invoke the email compose window from another program like via MS Word's Save and Send button in the backstage or Adobe Reader's "Attach to Email" functions, the ribbon button totally disappears!

    Commenting random bits of code for testing leads me to believe that invoking the Compose window from outside Outlook causes it to skip ThisAddIn.

    Does anyone have specifics of how exactly outlook reacts to the Save and Send button?

    Wednesday, February 23, 2011 11:23 PM

Answers

  • As I said earlier in the thread, when something like Word is used to open an email an Inspector window is opened. However while that Inspector is added to the Inspectors collection (since Outlook 2002), it does not fire the NewInspector() event of the Inspectors collection.
     
    To be able to detect that item if your addin is already running you need to use a timer. When the timer fires you need to check the Inspectors collection and if there are any Inspectors not being handled already you would handle them.
     
    In managed code a timer like that will fire on a background thread. The Outlook object model may not be accessed from a background thread, or you risk crashing or hanging Outlook. Therefore you would need to synchronize your code that handles the new Inspector back to the main addin thread so your object model code is running on the same thread as the Outlook UI.
     
    If your addin is not already running it will be opened in what's called "headless" mode. In that mode there is no ActiveExplorer in the Explorers collection (Explorers.Count == 0). So to know that you've been started by a Simple MAPI window you need to check for Explorers.Count and Inspectors.Count. If Explorers.Count == 0 in your Startup() event but Inspectors.Count != 0 then you just start handling that Inspector.
     
    Simple MAPI windows are always opened as modal Inspector windows. There is and always has been a problem with modal Inspector windows, when you interact with them in code they often leave a "ghost" when closed. That "ghost" window cannot be closed by normal means, and there is no Inspector in the Inspectors collection for it. It can be closed in the UI by clicking on the Close() box of the window.
     
    This applies not only to Simple MAPI windows, BTW, but to all Inspector windows opened modally, they are nothing but trouble and problems.
     
    What you often have to do after sending the item using code is to set up a timer in the send event that fires very shortly after the Send() event ends. I usually set the timer for something on the order of about 100 ms. In that timer event handler I synch back to the main thread and call the Close() event on the Inspector. That's something you need to do regardless of whether or not the item was a Simple MAPI item. 
     
    Then, if the item was a Simple MAPI item (I set a flag for those), I also force the window closed in the Inspector.Close() event handler. What I do is grab the window handle of the Inspector window using a pinvoke of FindWindow(). You supply that Win32 API call the caption of the window (Inspector.Caption) and the window class "rctrl_renwnd32". I do that when I first start handling the Inspector. I then use a pinvoke of PostMessage with a message of WM_CLOSE to that window, forcing it to close.
     
    That's pretty much how you have to handle Simple MAPI windows.
     
    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Kitler" <=?utf-8?B?S2l0bGVy?=> wrote in message news:873c52d6-d0ea-4800-89b1-30127c1ba05c...

    I haven't been able to locate those threads about MAPI handling and workarounds Ken, can you help me out here?

     

    From my own testing it seems that no properties in any other class may be accessed, like trying to MessageBox.Show() a string in ThisAddIn or global. But you can still use any methods in other classes.


    Ken Slovak MVP - Outlook
    • Marked as answer by Kit C Monday, February 28, 2011 8:42 PM
    Monday, February 28, 2011 2:29 PM

All replies

  • anyone at all?

    I've determined that if the action-on-click function of the toggle button is deemed impossible to execute, the button will not show up at all.

     

    My guess is that loading the compose form from another program will still load your add-in (because the ribbon button still appears is you make the toggle button do nothing on action), but is selective about what it chooses to load.

    Thursday, February 24, 2011 3:23 AM
  • That window is a modal Inspector window opened by Simple MAPI, which if Outlook is your MAPI handler will hand off the window to Outlook. Normally you can't handle that window in Outlook, as although it adds an item to the Inspectors collection it does not fire the NewInspector() event.
     
    There have been quite a few threads here and in the Outlook Development forum about handling Simple MAPI windows and the pitfalls you can run into and the workarounds you have to use.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Kitler" <=?utf-8?B?S2l0bGVy?=> wrote in message news:5e30e6d4-8b1f-49a5-97fb-a5424515993e...

    anyone at all?

    I've determined that if the action-on-click function of the toggle button is deemed impossible to execute, the button will not show up at all.

     

    My guess is that loading the compose form from another program will still load your add-in (because the ribbon button still appears is you make the toggle button do nothing on action), but is selective about what it chooses to load.


    Ken Slovak MVP - Outlook
    Thursday, February 24, 2011 2:37 PM
  • I haven't been able to locate those threads about MAPI handling and workarounds Ken, can you help me out here?

     

    From my own testing it seems that no properties in any other class may be accessed, like trying to MessageBox.Show() a string in ThisAddIn or global. But you can still use any methods in other classes.

    Sunday, February 27, 2011 9:09 PM
  • As I said earlier in the thread, when something like Word is used to open an email an Inspector window is opened. However while that Inspector is added to the Inspectors collection (since Outlook 2002), it does not fire the NewInspector() event of the Inspectors collection.
     
    To be able to detect that item if your addin is already running you need to use a timer. When the timer fires you need to check the Inspectors collection and if there are any Inspectors not being handled already you would handle them.
     
    In managed code a timer like that will fire on a background thread. The Outlook object model may not be accessed from a background thread, or you risk crashing or hanging Outlook. Therefore you would need to synchronize your code that handles the new Inspector back to the main addin thread so your object model code is running on the same thread as the Outlook UI.
     
    If your addin is not already running it will be opened in what's called "headless" mode. In that mode there is no ActiveExplorer in the Explorers collection (Explorers.Count == 0). So to know that you've been started by a Simple MAPI window you need to check for Explorers.Count and Inspectors.Count. If Explorers.Count == 0 in your Startup() event but Inspectors.Count != 0 then you just start handling that Inspector.
     
    Simple MAPI windows are always opened as modal Inspector windows. There is and always has been a problem with modal Inspector windows, when you interact with them in code they often leave a "ghost" when closed. That "ghost" window cannot be closed by normal means, and there is no Inspector in the Inspectors collection for it. It can be closed in the UI by clicking on the Close() box of the window.
     
    This applies not only to Simple MAPI windows, BTW, but to all Inspector windows opened modally, they are nothing but trouble and problems.
     
    What you often have to do after sending the item using code is to set up a timer in the send event that fires very shortly after the Send() event ends. I usually set the timer for something on the order of about 100 ms. In that timer event handler I synch back to the main thread and call the Close() event on the Inspector. That's something you need to do regardless of whether or not the item was a Simple MAPI item. 
     
    Then, if the item was a Simple MAPI item (I set a flag for those), I also force the window closed in the Inspector.Close() event handler. What I do is grab the window handle of the Inspector window using a pinvoke of FindWindow(). You supply that Win32 API call the caption of the window (Inspector.Caption) and the window class "rctrl_renwnd32". I do that when I first start handling the Inspector. I then use a pinvoke of PostMessage with a message of WM_CLOSE to that window, forcing it to close.
     
    That's pretty much how you have to handle Simple MAPI windows.
     
    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Kitler" <=?utf-8?B?S2l0bGVy?=> wrote in message news:873c52d6-d0ea-4800-89b1-30127c1ba05c...

    I haven't been able to locate those threads about MAPI handling and workarounds Ken, can you help me out here?

     

    From my own testing it seems that no properties in any other class may be accessed, like trying to MessageBox.Show() a string in ThisAddIn or global. But you can still use any methods in other classes.


    Ken Slovak MVP - Outlook
    • Marked as answer by Kit C Monday, February 28, 2011 8:42 PM
    Monday, February 28, 2011 2:29 PM
  • you seem to be talking about some C++ methods, I'm using C#, is there a similar alternative?

     

    Also, I still have an odd problem where externally invoking Outlook 2010 causes ThisAddIn to always start up after the modal Email.Compose Inspector closes, from what I see other people say about handling external calls, this isn't normal.

     

    Do you have any idea what could be causing this?

     

    This is a problem because any method I try to invoke that does not belong to the Ribbon's class will not appear. The Ribbon button will actually not appear in an external invoke unless I comment out all code that belong to other classes.

     

    To clarify again, I don't have a problem getting the Inspector of my Modal Compose window anymore, but ThisAddIn_Startup and any other classes cannot start/be invoked until the Email Compose(and the 'ghost' it leaves behind) are closed.

    Tuesday, March 01, 2011 8:13 PM
  • Everything I mentioned was and has been done using C#. I don't use C++ very much at all. You can call any Win32 API call as a managed code pinvoke, I do that all the time in C# and in VB.NET.
     
    I've used Simple MAPI handling with shared and VSTO addins going back to VSTO 2005 SE with no problems and I've used that methodology even before that with VB6 code. Outlook must start to handle the Simple MAPI Inspectors, what do you think is actually creating and handling the Inspector? It's Outlook.
     
    In cases where a prompt for profile is set up when Outlook starts you would have to select a profile, but Outlook will start and in theory at least the addin should also start. There won't be any Explorers, so trying to use those won't work. However, anything else in my addin code works under those circumstances.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Kit C" <=?utf-8?B?S2l0IEM=?=> wrote in message news:256ccb45-31b7-423f-a769-38b11057ef42...

    you seem to be talking about some C++ methods, I'm using C#, is there a similar alternative?

     

    Also, I still have an odd problem where externally invoking Outlook 2010 causes ThisAddIn to always start up after the modal Email.Compose Inspector closes, from what I see other people say about handling external calls, this isn't normal.

     

    Do you have any idea what could be causing this?

     

    This is a problem because any method I try to invoke that does not belong to the Ribbon's class will not appear. The Ribbon button will actually not appear in an external invoke unless I comment out all code that belong to other classes.

     

    To clarify again, I don't have a problem getting the Inspector of my Modal Compose window anymore, but ThisAddIn_Startup and any other classes cannot start/be invoked until the Email Compose(and the 'ghost' it leaves behind) are closed.


    Ken Slovak MVP - Outlook
    Wednesday, March 02, 2011 3:07 PM
  • Thanks for your answer again Ken, sorry if I seemed to offend, it's just that my understanding of Outlook is rather shallow.

     

    But thanks for helping me overcome that ghost window problem! :)

    Wednesday, March 02, 2011 9:32 PM
  • I wasn't offended at all, I apologize if what I said came across that way.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Kit C" <=?utf-8?B?S2l0IEM=?=> wrote in message news:db35cd87-2e4c-4ed0-b22d-8c9bdffdaaf7...

    Thanks for your answer again Ken, sorry if I seemed to offend, it's just that my understanding of Outlook is rather shallow.

     

    But thanks for helping me overcome that ghost window problem! :)


    Ken Slovak MVP - Outlook
    Thursday, March 03, 2011 2:55 PM
  • Grabbing the inspector window and forcing it to close helped a lot. Although: you can avoid implementing threads and timers by keeping track of which Inspectors are fired from the main Application and forcing those that aren't to close.

    See: http://social.msdn.microsoft.com/Forums/is/outlookdev/thread/688ed11a-59e4-4778-b956-fc8a7cbaec14 for details of this mechanism and sample code using FindWindow and PostMessage.

    Monday, March 07, 2011 4:22 PM