在什么情况下Internet Explorer无法正确卸载ActiveX控件?

问题描述:

我遇到了一个令人困惑的问题,我正在写一个ActiveX控件 - 有时,Internet Explorer似乎无法正确卸载过程关闭控件。这导致控件实例的析构函数不被调用。在什么情况下Internet Explorer无法正确卸载ActiveX控件?

该控件是用C++编写的,使用ATL并使用Visual Studio 2005编译。控件实例的析构函数总是在用户浏览控件所嵌入的页面时调用 - 问题只发生在浏览器关闭。当我在调试器下运行IE时,我没有看到任何异常 - 调试器没有发现任何异常,访问冲突或断言失败,但问题仍然存在 - 我可以在控件中设置断点析构函数,当我关闭浏览器时它从来没有被打。

此外,当我加载一个嵌入控件的多个实例的简单HTML页面时,我没有看到问题。这个问题似乎只发生在控件从我们的web应用程序实例化的时候,它会动态地将标签插入到网页中 - 当然,不知道是什么原因导致了这个问题,我不知道这一点信息是否相关,但它似乎表明这可能是一个IE问题,因为它依赖于数据。

当我在调试器下运行简单的测试用例时,我可以在控件的析构函数中设置一个断点,并且每次都会触发它。我相信这排除了控制本身的问题(比如说,一个会阻止析构函数被称为接口泄漏的错误)。

我使用IE 6测试了大部分测试,但我在IE 7上也发现问题。我还没有测试过IE 8

我现在的工作假设是动态HTML代码中有一些东西导致浏览器泄漏ActiveX控件上的一个接口。到目前为止,我还没有能够生成一个能够在应用程序之外重现此类应用程序的好测试用例,而且该应用程序有点太大而无法做出好的测试用例。

我希望有人能够提供洞察,可能会导致这种行为的IE错误。顺便提一下,下面提供的答案太笼统了 - 我正在寻找一系列已知导致此情况的具体情况。当然有人在那里见过这个。

要调试COM中C++中未调用对象(C++)析构函数的问题,最好的方法是关注COM对象的引用计数如何递增或递减。可能发生的情况是,有人正在多次增加该次数,然后不会递减相同的次数。这导致对象不被释放。

您的动态HTML可能只是简单地在IE中显示一个错误,如果您使用静态页面,则不会发生这种错误。

如果IE中存在一个错误,诀窍就是找出导致错误出现的原因,以及如何欺骗IE以正确释放COM对象(例如,使HTML消失)。

+0

感谢您的建议。动态的HTML代码是足够多毛的,没有人确定它是如何工作的,我试图解开它足以创建一个再现问题的测试用例迄今为止失败了。 – 2008-09-16 23:15:05

另一种方法 - 将清理代码添加到您的DllMain函数(如果该函数尚不存在,则添加该函数)。然后,无论引用计数(和引用计数错误),当你的DLL卸载可以清理自己了:

BOOL WINAPI DllMain(HINSTANCE, DWORD dwReason, LPVOID) { 
    if (dwReason == DLL_PROCESS_DETACH) { 
     CleanUpAnyObjectsStillAlive(); 
    } 
} 

哦,提醒一句 - 不要花太长的时间做你清理 - 如果你做,我不能保证过程关机不会杀死你。

+0

你知道在一个用MFC编写的控件中不能这样做,对吧? – 2008-10-06 15:08:24

+0

为什么?我不是MFC专家,但我不明白像MFC这样的库如果想要包含一个库,可以阻止*提供自己的DllMain。你的意思是MFC控件不提供清理它们的方法吗?如果是这样的话就会起哄。 – Bruce 2008-10-08 06:32:18

我有同样的问题,但只在特定的计算机上。 此计算机还存在Flash ActiveX问题,该问题在关闭该选项卡后仍保持有效状态。 我的猜测是问题不在于你的代码。你在其他电脑上有这个问题吗?