|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Loading forms in Main() to catch errors?
Hi,
I'm finally down to looking at ways to check whether our VB apps have all they have to run instead of just letting them crash and burn when loading a form that contains an OCX that has been replaced by a non-compatible version by another app... but I'm stuck at how to do this. Since Windows doesn't seem to provide a reliable way to check for dependencies, I was thinking of starting an EXE in Main(), load/unload each form in the EXE, and catch any error, but this type of code obviously doesn't work (VB won't even let me run/compile it, for that matter): ---------- CODE ---------------- Sub Main() OnError Goto ErrHandler Dim iCounter as Integer iCounter = 0 OnError Resume Next Do Err.Clear Load Form & iCounter If Err.Number = XXX then 'Form doesn't exist Exit Do ElseIf Err.Number = 336 Or Err.Number = 429 Or Err.Number = 50003 then 'Error loading form due to missing/wrong OCX MsgBox Err.Description,MB_CRITICAL,"Error loading Form" & iCounter End End if Unload Form & iCounter iCounter = iCounter + 1 Loop While True ErrHandler: MsgBox "ErrHandler" End Sub ---------- CODE ---------------- ... and parsing through the EXE looking for FormX (with X=0 to ...) doesn't seem too reliable :-) => How do you handle missing/wrong dependencies past the original install? Fred. |
|
#2
|
||||
|
||||
|
hmm... interesting question. Obviously, you can't do this in the form load procedure of the form containing the ocx. I wonder if you can execute a VBScript to determine the latest version of the OCX from the registry while a splash screen is loading?
|
|
#3
|
|||
|
|||
|
>>Obviously, you can't do this in the form load procedure of the form containing the ocx
Right, just add a module, create a Main() subroutine, and set the project to start on this routine, where you can check that your app has all its dependencies OK. >>I wonder if you can execute a VBScript to determine the latest version of the OCX from the registry while a splash screen is loading? Tried that, but it's a can of worms. Apart from maybe shelling out $700 to buy Desaware's VersionStamper which I haven't tried, there's no good way of checking dependencies, especially that you can call from an app at load time. For those interested, you can try DependencyWalker and Squealer when trying to build an installer, but those are not callable from the EXE itself. Do you just add an error handler in every Form_Load() to catch errors? Fred. |
|
#4
|
||||
|
||||
|
I would assume so, although I don't know what you would do with the error once you have it. What happened when you tried to check dependencies at load time? I'm sure that anything unregistered would give you a headache. Were you getting components with the version numbers unchanged?
|
|
#5
|
|||
|
|||
|
>>although I don't know what you would do with the error once you have it
Here's the ideal algo: 1. Start the app with Main() 2. Use a generic ForEach loop to fetch all the forms that live in the EXE, load/unload each form, and add an error handler that catches OCX-related errors, such as 339, 429, 50003, eg. Dim fForm as Form ForEach fForm in FormsInEXE Load fForm Unload fForm Next fForm 3. If any OCX-related error pops up, either repair the issue silently or by asking the user, or just display a messagebox explaining the issue and asking them to call us But, since there's no API to recurse through an EXE to list all its dependencies (OCX, at least), or its forms, at this point, I guess what we'll do is... 1. In Main() load/unload each form manually instead of using a generic ForEach loop, remembering to update this loop every time we add/remove a form in the project 2. If an error occurs, reregister either all the OCX's located in the app directory or just the offending OCX (by parsing Err.Description to know which OCX caused the error) 3. If the OCX can't be found in the app directory, either silently or explicitely fetch it from our site >> What happened when you tried to check dependencies at load time? I'm sure that anything unregistered would give you a headache. Were you getting components with the version numbers unchanged? Until now, we never handled this issue, so in case an OCX was missing (no, we didn't use an installer either :-)) or had been replaced by another app, the app would just crash whenever a form was loaded that required this component. Another headache is that our development hosts don't all have the same SP, so we would end up with EXE's that depended on different versions of MS ActiveX controls, causing quite a lot of hair pulling :-) But since we're about to ship a new app, I wanted to get to the bottom of this, and provide both error control/repair, and a good installer (NSIS.) BTW, I just got error 50003 when opening a VB project on a host where I just installed a brand new VB5SP3. The error was due to the usual 1.x TypeLib number in the VBP (or was it an FRM?). Does anyone know what a TypeLib is, and the relationship between a TypeLib version # and the OCX four-digit version number, if any? Thank you :-) Fred. PS: BTW, a list of the different version numbers for Microsoft components is available here: http://support.microsoft.com/defaul...nfo.asp&SD=msdn |
|
#6
|
||||
|
||||
|
sorry, I'm drawing a blank here. I wish I could help, but without knowing the dependencies, I can't think of anything
|
|
#7
|
|||
|
|||
|
No worries :-) I googled quite a bit, and there doesn't seem to be any API to extract either forms or dependencies from an EXE.
Now I understand why some people either went back to developing VB apps without any dependeny other than the runtime... or dumped VB entirely :-) Thx anyway Fred. |
|
#8
|
||||
|
||||
|
fred - thought of something. The file system object has a method called "getfileversion". It would require work, but could you include an INI with the version numbers of your OCX's and have it check against the version on the target PC. It has another method called "FileExists" that you might use, then nest the "GetFileVersion" to first determine if the OCX exists on the client PC, then determine if it's the right version or not. If it is not, then enter a routine that would download the new version to the client PC (maybe using FTP), and use the registry API calls to register the new version? It's just a thought.
|
|
#9
|
|||
|
|||
|
Thanks for the idea :-) I didn't know the file system obj, but I was thinking of doing something similar since I already have some API-based code to extract version infos and build INI files.
I was thinking of building a batch file that would 1. parse VBP, FRM, BAS, and DEP files for dependencies, and save those in an INI file 2. vb5.exe /make myproj.vbp 3. use eg. PEBundle or EXE Bundle to stick the INI inside the EXE 4. In Main(), loop through each entry in the INI file, and either just stop with an error message saying such and such component is N.A. or wrong version, and/or offer to download it from the Net Considering that the great majority of VB apps require components, I'm surprised this hasn't been streamlined. I've learned more about COM and install issues in a week than I ever wished to know :-) Thanks again for your great help Fred. |
|
#10
|
||||
|
||||
|
wow. That sounds really complicated. I think I'm going to try and implement the method I suggested in my programs from now on. I just realized that I could have a separate header for each control specified by the control name with a version and url entry. at run time, I can check the version, and if necessary , use the url to download the ocx from the proper site. Good luck with your implementation. If you don't mind, could you send me an example when you get it completed? I'd like a peek if I could
![]() |
|
#11
|
|||
|
|||
|
Just remember to set your form = nothing in the loop... otherwise you get extra code left in memory...
|
|
#12
|
|||
|
|||
|
Even when using Unload?
|
|
#13
|
|||
|
|||
|
For those interested, and since VB (5; I don't use VB6 yet) doesn't offer a function to list all the forms contained in an EXE to load them in a loop.... you can't help but doing a bit of hard-coding.
In that case, we might as well just load a single control instead of a whole form, since the issue we're trying to solve is checking in Main() whether any OCX can't be loaded (since we provide an installer, this means that the control has probably been replaced by an incompatible version). Here's some code: '=============== Sub Main() On Error GoTo ErrHandler Dim myCol As New Collection Dim MyObject As Variant Dim myObj As Object myCol.Add "MSComctlLib.TabStrip" myCol.Add "MSComCtl2.MonthView" For Each MyObject In myCol MsgBox MyObject Set myObj = CreateObject(MyObject) Set myObj = Nothing Next Form1.Show Exit Sub ErrHandler: MsgBox Err.Description, vbOKOnly, "Error n°" & Err.Number End Sub '=============== Since you made sure to keep a copy of all the OCX's you need in the app's directory, just add code in ErrHandler to either reregister all the OCX's in the current directory, or parse Err.Description to find which control is causing the problem, and just reregister this particular OCX. If the OCX can't be found or is corrupt, just download it from your web site :-) Fred. |
![]() |
| Viewing: Dev Shed Forums > Programming Languages - More > Visual Basic Programming > Loading forms in Main() to catch errors? |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|