Как подавить ошибку «Все еще активные COM-объекты в этом приложении» при закрытии приложения? - PullRequest
2 голосов
/ 29 сентября 2011

Я написал несколько ATL COM-объектов, которые используются для перетаскивания в моем приложении C ++ Builder.

По независящим от меня причинам мое приложение все еще имеет активные COM-объекты, когда пользователь пытается закрыть его. Это потому, что другие COM-клиенты, которые используют мои объекты, похоже, кэшируют мои COM-объекты и не освобождают их - в результате мои COM-объекты все еще имеют счетчик ссылок больше нуля, когда пользователь нажимает «X», чтобы закрыть мою программу , Это приводит к тому, что пользователь получает недружелюбное сообщение, подобное этому:

enter image description here

Я бы хотел, чтобы мое приложение молча прекратило работу и не задавало пользователю этот раздражающий вопрос.

Как мне подавить это сообщение?

Ответы [ 3 ]

3 голосов
/ 30 сентября 2011

Всплывающее сообщение отображается функцией обратного вызова TATLModule::AutomationTerminateProc() в файле atlmod.h.Он регистрируется обратным вызовом TATLModule::InitATLServer(), который вызывает функцию AddTerminateProc() VCL.Когда вызывается метод 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!
}
1 голос
/ 29 сентября 2011

Я нашел обходной путь для этого.Я оставлю этот вопрос открытым, если кто-нибудь отправит лучший метод, поскольку он зависит от недокументированных внутренних деталей реализации библиотек ATL / VCL C ++ Builder.

В основной форме поместите:

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

Появляется VCL для проверки количества блокировок и отображения этого раздражающего сообщения после Возникает событие запроса закрытия.Сообщение отображается только в том случае, если количество блокировок равно 0. Поэтому я установил счетчик блокировок равным 0, что приводит к тому, что сообщение не отображается.Я думаю, что это безопасно, потому что я искал в исходном коде ATL / VCL места, где используется счетчик блокировок, и я не нашел ничего, кроме кода, который проверяет, отображать ли это сообщение.

0 голосов
/ 29 сентября 2011

Попробуйте

TerminateProcess(GetCurrentProcess(), 0);

Конечно, если нет лучшего способа.

...