如何抑制“此应用程序中仍有活动的 COM 对象"关闭应用程序时出错?

如何抑制“此应用程序中仍有活动的 COM 对象

问题描述:

我编写了一些 ATL COM 对象,用于在我的 C++ Builder 应用程序中进行拖放操作.

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

由于我无法控制的原因,当用户尝试关闭我的应用程序时,它仍然具有活动的 COM 对象.这是因为使用我的对象的其他 COM 客户端似乎缓存了我的 COM 对象并且不释放它们 - 因此,当用户单击X"关闭我的程序时,我的 COM 对象的引用计数仍然大于零.这会导致用户收到如下不友好的消息:

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.

如何禁止显示此消息?

弹出消息由 atlmod.h 中的 TATLModule::AutomationTerminateProc() 回调函数显示.它由 TATLModule::InitATLServer() 回调注册,该回调调用 VCL 的 AddTerminateProc() 函数.当 TForm::Close() 方法被调用时,它会调用 CallTerminationProcs() 来查看应用程序是否可以安全关闭,然后调用 TATLModule::AutomationTerminateProc().

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().

如果您不提供自己的初始化回调,TATLModule 构造函数将调用 InitATLServer().因此,为了避免弹出窗口,只需在项目的主 .cpp 文件中传入一个自定义回调,该回调执行 TATLModule::InitATLServer() 除了调用 AddTerminateProc() 之外通常所做的所有事情,例如:

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