![]() |
If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. |
|
|
Thread Tools | Search this Thread | Display Modes |
|
#1
|
|||
|
|||
![]()
Hello all.
I've been developing a C# Addin for OL2002/2003 and encountered a strange problem. Sometimes inspector's Close event is fired before the Activate handler finishes. This can be reproduced by opening many inspectors and then closing them sequentially as fast as possible. Logs show that Close handler is invoked before the Activate handler finishes. Both handlers are executed in the same thread. As you can imagine, this causes numerous problems, since the Close handler frees resources allocated on Inspector creation. First I thought that the reason might be an invokation of the message loop (by calling Application.DoEvents() for example) hidden somewhere inside Activate handler or its callees. But a thorough code analysis showed this is not the case (at least in the addin). However the Activate handler makes many calls to the Outlook object model. I've made some protection from this situation: I don't free any resources (that is normally done on Close) until Activate handler finishes. But it looks like Outlook sometimes releases its internal objects before Close event is fired, so Activate event handler cannot continue - any access to Outlook object model causes either a null reference exception or a "COM wrapper" exception. Does anybody know the real cause of that? Does my addin do something wrong, or is it an Outlook's "feature"? The only workaround that comes in mind is creating proxies for Outlook objects to use them in Activate event handler (as well as in all other handlers). These proxies would check if the inspector is "closed" before any real operations. But this decision is quite costly. Is there a simpler solution? Any help would be really appreciated. Thanks in advance. WBR, Sergey Anchipolevsky |
#2
|
|||
|
|||
![]()
If your code in the Activate event handler does anything that can
potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool "Sergey Anchipolevsky" wrote in message .com... Hello all. I've been developing a C# Addin for OL2002/2003 and encountered a strange problem. Sometimes inspector's Close event is fired before the Activate handler finishes. This can be reproduced by opening many inspectors and then closing them sequentially as fast as possible. Logs show that Close handler is invoked before the Activate handler finishes. Both handlers are executed in the same thread. As you can imagine, this causes numerous problems, since the Close handler frees resources allocated on Inspector creation. First I thought that the reason might be an invokation of the message loop (by calling Application.DoEvents() for example) hidden somewhere inside Activate handler or its callees. But a thorough code analysis showed this is not the case (at least in the addin). However the Activate handler makes many calls to the Outlook object model. I've made some protection from this situation: I don't free any resources (that is normally done on Close) until Activate handler finishes. But it looks like Outlook sometimes releases its internal objects before Close event is fired, so Activate event handler cannot continue - any access to Outlook object model causes either a null reference exception or a "COM wrapper" exception. Does anybody know the real cause of that? Does my addin do something wrong, or is it an Outlook's "feature"? The only workaround that comes in mind is creating proxies for Outlook objects to use them in Activate event handler (as well as in all other handlers). These proxies would check if the inspector is "closed" before any real operations. But this decision is quite costly. Is there a simpler solution? Any help would be really appreciated. Thanks in advance. WBR, Sergey Anchipolevsky |
#3
|
|||
|
|||
![]()
He should be able to find out exactly what is causing the re-entrance by
setting a breakpoint in the Close event handler and then looking at the stack trace to see what the Activate event handler calls into that leads to Close. From what I understand, there are alot of API's that can cause re-entrance bugs by pumping the message queue that you might not be aware of such as waiting on waithandles, sleeping threads, etc. There's a ton of information about this problem over on cbrummes web log. http://blogs.msdn.com/cbrumme/archiv.../02/66219.aspx -- Josh Einstein Einstein Technologies Microsoft Tablet PC MVP Tablet Enhancements for Outlook 2.0 - Try it free for 14 days www.tabletoutlook.com "Dmitry Streblechenko" wrote in message ... If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool "Sergey Anchipolevsky" wrote in message .com... Hello all. I've been developing a C# Addin for OL2002/2003 and encountered a strange problem. Sometimes inspector's Close event is fired before the Activate handler finishes. This can be reproduced by opening many inspectors and then closing them sequentially as fast as possible. Logs show that Close handler is invoked before the Activate handler finishes. Both handlers are executed in the same thread. As you can imagine, this causes numerous problems, since the Close handler frees resources allocated on Inspector creation. First I thought that the reason might be an invokation of the message loop (by calling Application.DoEvents() for example) hidden somewhere inside Activate handler or its callees. But a thorough code analysis showed this is not the case (at least in the addin). However the Activate handler makes many calls to the Outlook object model. I've made some protection from this situation: I don't free any resources (that is normally done on Close) until Activate handler finishes. But it looks like Outlook sometimes releases its internal objects before Close event is fired, so Activate event handler cannot continue - any access to Outlook object model causes either a null reference exception or a "COM wrapper" exception. Does anybody know the real cause of that? Does my addin do something wrong, or is it an Outlook's "feature"? The only workaround that comes in mind is creating proxies for Outlook objects to use them in Activate event handler (as well as in all other handlers). These proxies would check if the inspector is "closed" before any real operations. But this decision is quite costly. Is there a simpler solution? Any help would be really appreciated. Thanks in advance. WBR, Sergey Anchipolevsky |
#4
|
|||
|
|||
![]()
Hello Josh,
He should be able to find out exactly what is causing the re-entrance by setting a breakpoint in the Close event handler and then looking at the stack trace to see what the Activate event handler calls into that leads to Close. Oh.. How could I miss it? Shame on me! Thank you very much :-) If you're insterested in my findings see my reply to Dmitry in this thread. From what I understand, there are alot of API's that can cause re-entrance bugs by pumping the message queue that you might not be aware of such as waiting on waithandles, sleeping threads, etc. There's a ton of information about this problem over on cbrummes web log. http://blogs.msdn.com/cbrumme/archiv.../02/66219.aspx Oh yes. I shoud be careful. Thank you for the source. "Dmitry Streblechenko" wrote in message ... If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool "Sergey Anchipolevsky" wrote in message .com... Hello all. I've been developing a C# Addin for OL2002/2003 and encountered a strange problem. Sometimes inspector's Close event is fired before the Activate handler finishes. This can be reproduced by opening many inspectors and then closing them sequentially as fast as possible. Logs show that Close handler is invoked before the Activate handler finishes. Both handlers are executed in the same thread. As you can imagine, this causes numerous problems, since the Close handler frees resources allocated on Inspector creation. First I thought that the reason might be an invokation of the message loop (by calling Application.DoEvents() for example) hidden somewhere inside Activate handler or its callees. But a thorough code analysis showed this is not the case (at least in the addin). However the Activate handler makes many calls to the Outlook object model. I've made some protection from this situation: I don't free any resources (that is normally done on Close) until Activate handler finishes. But it looks like Outlook sometimes releases its internal objects before Close event is fired, so Activate event handler cannot continue - any access to Outlook object model causes either a null reference exception or a "COM wrapper" exception. Does anybody know the real cause of that? Does my addin do something wrong, or is it an Outlook's "feature"? The only workaround that comes in mind is creating proxies for Outlook objects to use them in Activate event handler (as well as in all other handlers). These proxies would check if the inspector is "closed" before any real operations. But this decision is quite costly. Is there a simpler solution? Any help would be really appreciated. Thanks in advance. WBR, Sergey Anchipolevsky WBR, Sergey Anchipolevsky |
#5
|
|||
|
|||
![]()
Hello Dmitry,
If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? I followed Josh's advice and found out that the message loop is pumped in CommandBars.GetEnumerator(). (very surprising actually). I use this method to iterate through toolbar buttons and menu items in order to hide some of them upon inspector activation. I implemented the following workaround that seems to work quite well. I subclassed the inspector's window with the code that suppresses WM_CLOSE message when it comes while the Activate handler is running. In the end of the Activate method I explicitly call Inspector.Close() if WM_CLOSE message has been received. What do you think about this solution? WBR, Sergey Anchipolevsky |
#6
|
|||
|
|||
![]()
If you have a reference to any .NET form or control you can use BeginInvoke
to "defer" the event until the next time the loop is pumped. For example: private bool _activating = false; private void Inspector_Activate() { { try { _activating = true; // do stuff which might pump the loop } // try finally { _activating = false; } // finally } // function private void Inspector_Close() { if ( _activating ) { myControl.BeginInvoke(new MethodInvoker(Inspector_Close)); return; } // if else{ // Proceed normally } // else } // function -- Josh Einstein Einstein Technologies Microsoft Tablet PC MVP Tablet Enhancements for Outlook 2.0 - Try it free for 14 days www.tabletoutlook.com "Sergey Anchipolevsky" wrote in message .com... Hello Dmitry, If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? I followed Josh's advice and found out that the message loop is pumped in CommandBars.GetEnumerator(). (very surprising actually). I use this method to iterate through toolbar buttons and menu items in order to hide some of them upon inspector activation. I implemented the following workaround that seems to work quite well. I subclassed the inspector's window with the code that suppresses WM_CLOSE message when it comes while the Activate handler is running. In the end of the Activate method I explicitly call Inspector.Close() if WM_CLOSE message has been received. What do you think about this solution? WBR, Sergey Anchipolevsky |
#7
|
|||
|
|||
![]()
Hello Josh,
I'm affraid, your solution isn't exactly what I need, because it deffers my event handling, not the event itself. When I leave Inspector_Close() after calling BeginInvoke(), Outlook will destroy the Inspector's objects. And when my finalizing code (the other branch in Inspector_Close()) is finally starts executing, I'll still have the same problem that I had before supressing WM_CLOSE - COM wrapper exceptions. Am I wrong? WBR, Sergey Anchipolevsky If you have a reference to any .NET form or control you can use BeginInvoke to "defer" the event until the next time the loop is pumped. For example: private bool _activating = false; private void Inspector_Activate() { { try { _activating = true; // do stuff which might pump the loop } // try finally { _activating = false; } // finally } // function private void Inspector_Close() { if ( _activating ) { myControl.BeginInvoke(new MethodInvoker(Inspector_Close)); return; } // if else{ // Proceed normally } // else } // function "Sergey Anchipolevsky" wrote in message .com... Hello Dmitry, If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? I followed Josh's advice and found out that the message loop is pumped in CommandBars.GetEnumerator(). (very surprising actually). I use this method to iterate through toolbar buttons and menu items in order to hide some of them upon inspector activation. I implemented the following workaround that seems to work quite well. I subclassed the inspector's window with the code that suppresses WM_CLOSE message when it comes while the Activate handler is running. In the end of the Activate method I explicitly call Inspector.Close() if WM_CLOSE message has been received. What do you think about this solution? WBR, Sergey Anchipolevsky |
#8
|
|||
|
|||
![]()
That should work, but... Why do you need to enumerate through *all* controls
in an inspector? If you are using the Word editor, there could be thousands of them. Do you really care about all of them? Did you try to use FindControl() instead to only work with the controls thata you care about? Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool "Sergey Anchipolevsky" wrote in message .com... Hello Dmitry, If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? I followed Josh's advice and found out that the message loop is pumped in CommandBars.GetEnumerator(). (very surprising actually). I use this method to iterate through toolbar buttons and menu items in order to hide some of them upon inspector activation. I implemented the following workaround that seems to work quite well. I subclassed the inspector's window with the code that suppresses WM_CLOSE message when it comes while the Activate handler is running. In the end of the Activate method I explicitly call Inspector.Close() if WM_CLOSE message has been received. What do you think about this solution? WBR, Sergey Anchipolevsky |
#9
|
|||
|
|||
![]()
Hello Dmitry,
I need the overall enumeration because I have to disable many functions that aren't consistent with my custom form's functionality. To be more specific, I have a list of controls that should be left enabled in the custom form. The rest of the buttons must be hidden. This is a project requirement. Also, the addin must work under different versions of Outlook which have different sets of buttons. Since I don't know a priori the exact set of controls to be hidden, I cannot use FindControl(), but I can iterate over all the controls and determine if this one must be hidden or not. WBR, Sergey Anchipolevsky That should work, but... Why do you need to enumerate through *all* controls in an inspector? If you are using the Word editor, there could be thousands of them. Do you really care about all of them? Did you try to use FindControl() instead to only work with the controls thata you care about? Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool "Sergey Anchipolevsky" wrote in message .com... Hello Dmitry, If your code in the Activate event handler does anything that can potentially run the Windows message loop (such sa displaying a message box or any other window), then Close event can potentially fire while Activate is still beign processed. What do you do in the Activate event handler? I followed Josh's advice and found out that the message loop is pumped in CommandBars.GetEnumerator(). (very surprising actually). I use this method to iterate through toolbar buttons and menu items in order to hide some of them upon inspector activation. I implemented the following workaround that seems to work quite well. I subclassed the inspector's window with the code that suppresses WM_CLOSE message when it comes while the Activate handler is running. In the end of the Activate method I explicitly call Inspector.Close() if WM_CLOSE message has been received. What do you think about this solution? WBR, Sergey Anchipolevsky |
Thread Tools | Search this Thread |
Display Modes | |
|
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Outlook 2003 fires an Inspector Close when a send is cancelled | Steve D | Add-ins for Outlook | 8 | February 8th 06 11:22 PM |
how do activate spellckeck in OE | FerrisJ | Outlook - Installation | 2 | February 7th 06 02:49 PM |
How to find out which is the current item shown in the inspector? | Michael Reukauff | Add-ins for Outlook | 1 | January 25th 06 02:33 PM |
how to add commandbarbutton to inspector window | Ram | Outlook - General Queries | 1 | January 18th 06 08:42 PM |
how to add commandbarbutton to inspector window | Ram | Add-ins for Outlook | 0 | January 18th 06 03:18 PM |