James Johnston
James Johnston

Reputation: 9492

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

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:

enter image description here

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

How do I suppress this message?

Upvotes: 2

Views: 4080

Answers (3)

Remy Lebeau
Remy Lebeau

Reputation: 597490

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!
}

Upvotes: 3

James Johnston
James Johnston

Reputation: 9492

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.

Upvotes: 1

Alex F
Alex F

Reputation: 43331

Try

TerminateProcess(GetCurrentProcess(), 0);

Of course, if there is no better way.

Upvotes: 0

Related Questions