I have a VB6 app that has a ton of 3rd party components. The app works well, but on exit (and only when running as a standalone EXE, e.g. not in the IDE), it pops up an error message:
I've seen errors like these before but typically it says which component is missing dependencies or is not registered properly.
I ran it through Process Monitor and got the following files that it cannot find:
And then it quits. I googled the file names that it cannot find and can't seem to find anything. It seems like its searching for a variation of MSComENU, MSComEN and MSCOENU dlls.
I checked and rechecked to make sure that all the the 3rd party components are there and they are - the application functions fine, it wouldn't if they weren't there.
It is worth noting that error occurs after the last line of VB6 code (in Form_Unload
event) has fired. I know this because the last line is a message box that does appear.
Much, much later EDIT: I finally got back to dealing with the problem and figured it out by process of elimination (and it was a loooong process). In the end it had nothing to do with any MSCOMM*.dll entries. In fact, I do not know why they still show up in Process Monitor. The problem was much simpler.
I had several 3rd party controls on the main form. In an effort not to pollute the main form with a ton of event handling code, I delegated these controls to a new class, like so:
' 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 ...'
What was missing was code to explicitly deallocate these objects prior to closing. This is something that Visual Basic typically does. So I added the following in the Form_QueryClose in the main form:
With moDelegateObject
Set .ThirdPartyCtlHandler1 = Nothing
Set .ThirdPartyCtlHandler2 = Nothing
Set .ThirdPartyCtlHandler3 = Nothing
End with
Set moDelegateObject = Nothing
Last line turned out to be superflous, but I threw it in there for completeness sake. I think it was a combination of delegating controls to a delegate class and receiving events from it in the Main form and using a good number of really obscure 3rd party controls which contributed to this problem. It is probable that the 3rd party control does not cleanly deallocates itself. Anyway, lesson learned.