How to suppress “There are still active COM objects in this application” error when closing application?

狂风中的少年 提交于 2019-12-06 09:50:39

问题


I've written a few ATL COM objects that are used for drag-and-drop within my C++ Builder application.

Due to reasons beyond my control, my application still has active COM objects when the user attempts to close it. This is because other COM clients that use my objects seem to cache my COM objects and don't release them - as a result, my COM objects still have a reference count greater than zero when the user clicks the "X" to close my program. This results in the user getting an unfriendly message like this:

I would like my application to silently terminate and not ask the user this annoying question.

How do I suppress this message?


回答1:


The popup message is displayed by the the TATLModule::AutomationTerminateProc() callback function in atlmod.h. It is registered by the TATLModule::InitATLServer() callback, which calls the VCL's AddTerminateProc() function. When the TForm::Close() method is called, it calls CallTerminationProcs() to see if the app can safely close, which then calls TATLModule::AutomationTerminateProc().

The TATLModule constructor calls InitATLServer() if you do not provide your own initialization callback. So to avoid the popup, simply pass in a custom callback in your project's main .cpp file that does everything TATLModule::InitATLServer() normally does other than call AddTerminateProc(), eg:

void __fastcall MyInitATLServer();

TComModule _ProjectModule(&MyInitATLServer); // <-- here
TComModule &_Module = _ProjectModule;

BEGIN_OBJECT_MAP(ObjectMap)
  ...
END_OBJECT_MAP()

void __fastcall MyInitATLServer()
{
    if (TComModule::SaveInitProc)
        TComModule::SaveInitProc();

    _Module.Init(ObjectMap, Sysinit::HInstance);
    _Module.m_ThreadID = ::GetCurrentThreadId();
    _Module.m_bAutomationServer = true;
    _Module.DoFileAndObjectRegistration();
    // AddTerminationProc(AutomationTerminationProc); // <-- no more popup!
}



回答2:


I found a workaround for this. I'll leave this question open in case anyone posts a better method, since this one is dependent on undocumented internal implementation details of C++ Builder's ATL/VCL libraries.

In the main form, place:

extern TComModule &_Module;
void __fastcall TMainAppForm::FormCloseQuery(TObject *Sender, bool &CanClose)
{
    _Module.m_nLockCnt = 0;

VCL appears to check the lock count and display this annoying message after the close query event is raised. It only displays the message if the lock count is 0. Therefore, I set the lock count to 0 which causes the message to not be shown. I think it's harmless to do, because I searched the ATL/VCL source code for places where the lock count is used, and I didn't find anything other than the code that checks whether to display this message.




回答3:


Try

TerminateProcess(GetCurrentProcess(), 0);

Of course, if there is no better way.



来源:https://stackoverflow.com/questions/7601204/how-to-suppress-there-are-still-active-com-objects-in-this-application-error-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!