EduardoVB / SSTabEx

SSTab replacement for VB6. Themed (Windows visual styles)
10 stars 5 forks source link

EbMode and EbIsResetting need guarding #1

Closed WaynePhillipsEA closed 2 years ago

WaynePhillipsEA commented 2 years ago

At the moment SSTabEx cannot be used in twinBASIC. The first problem is that the calls to the VB5/6 IDE functions EbMode and EbIsResetting are crashing when called by your code.

The issue here is that twinBASIC is referencing your SSTabEx type library, which in turn references the type library inside VBA6.DLL. This causes VBA6.DLL to be loaded as a module into memory, but the VB6 IDE is of course not initialized at all. When the IDE hasn't been initialized/loaded, EbMode and EbIsResetting will hard crash.

Before calling the EbMode and EbIsRestting functions, you are correctly checking to see if either VBA5.DLL or VBA6.DLL is loaded (with GetModuleHandle), but that is not enough because the DLL can be loaded but not in an initialized state as above, so you will need to find a method to determine if it is actually safe to call EbMode/EbIsResetting, before calling them.

There's probably a few options here, but one way to do that is to use the EbGetExecuttingProj function. If the returned project is Nothing, then don't bother calling EbMode or EbIsResetting:

' I don't have VB5 to test if EbGetExecutingProj exists there, but I assume it does.
Private Declare Function EbGetExecutingProjVBA5 Lib "vba5" Alias "EbGetExecutingProj" (ByRef hProject As IUnknown) As Long
Private Declare Function EbGetExecutingProjVBA6 Lib "vba6" Alias "EbGetExecutingProj" (ByRef hProject As IUnknown) As Long
Private Function IsVBIDEProjectLoaded() As Boolean
    Dim projectUnk As IUnknown
    Select Case VBAEnvironment
        Case 5
            EbGetExecutingProjVBA5 projectUnk
        Case 6
            EbGetExecutingProjVBA6 projectUnk
    End Select
    IsVBIDEProjectLoaded = Not (projectUnk Is Nothing)
End Function

After changing the InBreakMode and IsResetting procedures to first check IsVBIDEProjectLoaded, we can at least now add SSTabEx to a tB Form:

tbSSTabEx
EduardoVB commented 2 years ago

I think that code was only necessary when the control runs in source code.

Then I added:

    Dim iInIDE As Boolean

    Debug.Assert MakeTrue(iInIDE)
    If iInIDE Then
        ' code
    End If

That avoids to run the code compiled, that code does not even gets compiled (using that call Debug.Assert MakeTrue(iInIDE)).

Let's see what happens.

I'm having trouble debugging the control for anything than VB6. I tried to add it to VBA Word and VBA Access and I get "Error 0". I don't know how to debug for tB or VBA.

I've set in the VB6 IDE, in Project properties, Debugging, Start program the tB path, but could not get the SStabEx icon to appear in the toolbox in tB.

I tried with the VB6 IDE running as admin and also as normal user. No results.

Without being able to debug (run in source code), it is hard (almost impossible) for me to fix bugs. IDK if Krool have been debugging his controls consuming them from tB and running in source code in VB6?

Thanks for your report. Perhaps that particular thing now is working?

WaynePhillipsEA commented 2 years ago

Thanks. I probably won't get chance to check this until tomorrow, but I would expect that change you made to fix that issue.

With regard VB6 debugging, it will be tricky with tB because the controls get instantiated from the background compiler process, not from the root IDE process.

WaynePhillipsEA commented 2 years ago

BTW, the next release of tB supports SSTabEx once this issue is fixed (including adding controls to tabs). I had to ensure the exposed ContainedControls by tB support the VB6 Control interface to avoid the Error 0 error. SSTab only required them to support IDispatch (Object).

EduardoVB commented 2 years ago

With regard VB6 debugging, it will be tricky with tB because the controls get instantiated from the background compiler process, not from the root IDE process.

When we are able to compile the controls in tB, that won't be necessary anymore. But now if we need to track bugs that only occur in tB but we are still compiling the controls in VB6, it will be very welcome to have the ability to run them the source code (if any there is chance at all).

WaynePhillipsEA commented 2 years ago

tB IDE and compiler EXEs offer some undocumented debug command line switches so that you can launch them individually (and even on different machines if necessary). So it should be possible to have VB6 launch the tB compiler process for debugging purposes. I'll let you know the command line switches tomorrow.

EduardoVB commented 2 years ago

I had to ensure the exposed ContainedControls by tB support the VB6 Control interface to avoid the Error 0 error.

Wayne, if you prefer I can change that to Object (instead of VBRUN.ContainedControls). I guess perhaps nobody is using that property still 😁

Anyway, sooner or later I think you'll need to support that type (for the UserControl quite surely). But if it is complicate to do it now, and you want this control to be supported in tB now, I could change that to Object type. Just let me know.

WaynePhillipsEA commented 2 years ago

The problem wasn't the ContainedControls collection itself, but the way you're enumerating the individual elements as Control types (which is an interface that non-VB6 controls won't support).

But anyway it's fine; it's fixed in the next tB release for tomorrow. tB actually already supported the 'Control' interface on all controls at runtime, but the issue was that at IDE time the ContainedControls collection is specially simulated by the tB compiler to match the controls from the live form designer, and I forgot to allow for theControl base interface there.

EduardoVB commented 2 years ago

Ahh, then it is entirely something else.

Do you mean that I should not use the As Control type when enumerating controls of the host or contained controls internally, I mean, in the private code?

Yeah, perhaps I should try to change to As Object to see if that can fix the compatibility with VBA environments too.

WaynePhillipsEA commented 2 years ago

Yes, that's right. It will help with compatibility to change it to Object for sure, but you might find some hosts still won't play nice. For example, I know MS Access doesn't support container activeX controls.

WaynePhillipsEA commented 2 years ago

Confirmed fixed in your latest release. Thanks! I'll close this, but I'll add a further comment here once I've published the details on the tB IDE/compiler command line switches mentioned earlier.

WaynePhillipsEA commented 2 years ago

So I won't document this officially just yet because I couldn't get it to work with VB6 debugging at the moment. But I'll detail how it should work, for now in case anyone wants to dig deeper:

To start the background compiler process manually, use the following command line: bin\twinBASIC_win32.exe --hostPort=8075 (that is what you should put in the VB6 Project Properties > Debugging > Start Program entry)

Then to start the IDE and connect to that compiler instance, use the command line: twinBASIC.exe --debug (with the --debug switch, the IDE will listen on port 8075)

With having to run VB6 with the Run As Administrator option, you'll also need to ensure the IDE executable is launched from a command line with the the Run As Administrator option. The compiler background process should be launched before the IDE process for this to work.

But unfortunately I couldn't get it to work here alongside the VB6 debugger. As soon as you launch the VB6 debugger, it appears the COM class registration of the class is not quite right, with attempts to create an instance of SSTabEx resulting in 'class not registered' errors. I haven't looked into it any deeper than that. Perhaps you'll have more luck than me.

EduardoVB commented 2 years ago

Wayne, thanks for the info. I usually run the VB6 IDE not as admin, but as normal user.

Maybe that could work. I try to test that later.

BTW, I have been able to debug the problems with VBA, I did it the hard way: putting logging points in every procedure. I already published the new version, I guess for tB there is no change.

EduardoVB commented 2 years ago

To start the background compiler process manually, use the following command line: bin\twinBASIC_win32.exe --hostPort=8075 (that is what you should put in the VB6 Project Properties > Debugging > Start Program entry)

Then to start the IDE and connect to that compiler instance, use the command line: twinBASIC.exe --debug (with the --debug switch, the IDE will listen on port 8075)

With having to run VB6 with the Run As Administrator option, you'll also need to ensure the IDE executable is launched from a command line with the the Run As Administrator option. The compiler background process should be launched before the IDE process for this to work.

I followed the instructions but could not get it to work.

imagen