У меня есть приложение VB6, в котором есть тонна сторонних компонентов. Приложение работает хорошо, но при выходе (и только при запуске в качестве автономного EXE, например, не в среде IDE) оно выдает сообщение об ошибке:
Я видел подобные ошибки раньше, но обычно в нем говорится, какой компонент является отсутствуют зависимости или не зарегистрирован должным образом.
Я запустил его через Process Monitor и получил следующие файлы, которые он не может найти:
И затем он закрывается. Я искал в Google имена файлов, которые он не может найти и ничего не может найти. Похоже, он ищет вариант DLL MSComENU, MSComEN и MSCOENU.
Я проверил и перепроверил еще раз, чтобы убедиться, что все сторонние компоненты есть, и они есть - приложение работает нормально, если бы их не было, этого бы не произошло.
Стоит отметить, что ошибка возникает после запуска последней строки кода VB6 (в событии Form_Unload
). Я знаю это, потому что последняя строка - это появившееся окно сообщения.
Намного, намного позже РЕДАКТИРОВАТЬ : Я наконец вернулся к решению проблемы и решил ее путем исключения (а это был долгий процесс). В конце концов, это не имело ничего общего с записями MSCOMM * .dll. На самом деле, я не знаю, почему они все еще отображаются в Process Monitor. Проблема была намного проще.
У меня было несколько сторонних элементов управления на главной форме.Чтобы не засорять основную форму тоннами кода обработки событий, я делегировал эти элементы управления новому классу, например:
' declaration code in main form'
Private WithEvents moDelegateObject as clsDelegateObject
' still in the main form, after initialization'
Set moDelegateObject = new clsDelegateObject
With moDelegateObject
Set .ThirdPartyCtlHandler1 = me.ThirdPartyCtl1
Set .ThirdPartyCtlHandler2 = me.ThirdPartyCtl2
Set .ThirdPartyCtlHandler3 = me.ThirdPartyCtl3
end with
' declarations and properties inside of clsDelegateObject'
Private WithEvents moThirdPartyCtlHandler1 as ThirdPartyCtl
Private WithEvents moThirdPartyCtlHandler2 as ThirdPartyCtl
Private WithEvents moThirdPartyCtlHandler3 as ThirdPartyCtl
Public Event FooEvent() ' other various events as well '
Public Property Set ThirdPartyCtlHandler1(o as ThirdPartyCtl)
moThirdPartyCtlHandler1 = o
End Property
Public Property Get ThirdPartyCtlHandler1() as ThirdPartyCtl
ThirdPartyCtlHandler1 = moThirdPartyCtlHandler1
End Property
' ... Repeat for each handler ...'
Не хватало кода для явного освобождения этих объектов перед закрытием. Это то, что обычно делает Visual Basic. Поэтому я добавил следующее в Form_QueryClose в основной форме:
With moDelegateObject
Set .ThirdPartyCtlHandler1 = Nothing
Set .ThirdPartyCtlHandler2 = Nothing
Set .ThirdPartyCtlHandler3 = Nothing
End with
Set moDelegateObject = Nothing
Последняя строка оказалась лишней, но я добавил ее для полноты картины. Я думаю, что это была комбинация делегирования элементов управления классу делегата и получения событий от него в основной форме, а также использования большого количества действительно непонятных сторонних элементов управления, которые способствовали этой проблеме. Вероятно, что сторонний элемент управления не освобождает себя полностью. Так или иначе, урок усвоен.