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

发布于 2024-12-07 09:56:52 字数 329 浏览 1 评论 0原文

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

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

在此处输入图像描述

我希望我的应用程序静默终止而不是问用户这个恼人的问题。

如何抑制此消息?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

安静 2024-12-14 09:56:53

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

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

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

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!
}
七月上 2024-12-14 09:56:53

我找到了解决这个问题的方法。如果有人发布更好的方法,我将保留这个问题,因为这个方法依赖于 C++ Builder 的 ATL/VCL 库的未记录的内部实现细节。

在主窗体中,place:

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

VCL 会检查锁定计数,并在引发关闭查询事件后显示这条烦人的消息。仅当锁定计数为 0 时才会显示该消息。因此,我将锁定计数设置为 0,这会导致不显示该消息。我认为这样做是无害的,因为我在ATL/VCL源代码中搜索了使用锁计数的地方,除了检查是否显示此消息的代码之外没有找到任何其他内容。

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.

李不 2024-12-14 09:56:53

当然可以尝试

TerminateProcess(GetCurrentProcess(), 0);

一下,如果没有更好的办法。

Try

TerminateProcess(GetCurrentProcess(), 0);

Of course, if there is no better way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文