Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting missing component error in a VB6 application

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:

enter image description here

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:

enter image description here

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.

like image 332
AngryHacker Avatar asked Feb 04 '12 05:02

AngryHacker


2 Answers

This could be a DLL_PROCESS_DETACH or CoUninitialize problem. Raymond Chen's blog "The Old New Thing" has a couple of relevant articles:

  • When DLL_PROCESS_DETACH tells you that the process is exiting, your best bet is just to return without doing anything
  • Do you know when your destructors run? Part 1.
  • Quick overview of how processes exit on Windows XP
  • How you might be loading a DLL during DLL_PROCESS_DETACH without even realizing it
  • The thread that gets the DLL_PROCESS_DETACH notification is not necessarily the one that got the DLL_PROCESS_ATTACH notification

As you said these are 3rd party components. You could try to make smaller test cases until the problem disappears to pinpoint the buggy component. You could also try a native code debugger and analyze what code created the error message.

The simplest solution however to work around the issue is trying to force a specific load-order of all those components. In the Main() or startup form, try to use some functionality of each 3rd party component in a fixed order. If the bug still appears, change the order until the problem vanishes. That might work.

like image 130
Simon Avatar answered Oct 02 '22 12:10

Simon


You could try using dependency walker on the list of references in the project file to see if any of those third party files are missing dependencies. If no dependencies are missing then try registering the files again using regsvr32. If any of the regsvr32 commands fail then you may have found the component with missing dependencies.

like image 38
John B Avatar answered Oct 02 '22 14:10

John B