twinBASIC Update: October 22, 2023

On April 23, 2021, I helped Wayne Phillips introduce the world to twinBASIC at the Access DevCon Vienna conference.  I boldly predicted that twinBASIC (along with the Monaco editor) would replace VBA and its outdated development environment by 2025.  With that goal in mind, this weekly update is my attempt to keep the project fresh in the minds of the VBA development community.

Every Sunday, I will be providing updates on the status of the project, linking to new articles discussing twinBASIC, and generally trying to increase engagement with the project.  If you come across items that should be included here, tweet me @NoLongerSet or email me at mike at nolongerset dot com.

Here are some links to get involved with the project:


Highlights

Experimental vbWatchdog Support

Longtime readers will know this is a feature that is near and dear to my heart.  

It is no exaggeration to say that finding vbWatchdog changed my life as a VBA developer:

Error Handling Evolution
How you handle errors says a lot about you as a programmer. Most people evolve with experience in how they handle errors. From the most naïve to the most advanced, here is what that evolution looks like.

With the release of BETA 411, vbWatchdog is now available in twinBASIC, too.  

Here's the announcement from Wayne inside a brand new #vbwatchdog Discord channel:


[/begin WaynePhillipsEA]

Running out of time today to document this, but here's a quick example of how to use the new vbWatchdog integration in tB (requires BETA 411):

    Public Sub Main()
        SetThreadGlobalErrorTrap(AddressOf GlobalErrorTrap)
        SimulateAnError
    End Sub
    Public Sub SimulateAnError()
        MsgBox 1 / 0        ' div by zero
    End Sub
    Public Sub GlobalErrorTrap(ByVal ErrEx As ErrorContext)
        Select Case ErrEx.State
            Case OnErrorStatus.OnErrorGoto0
                ' It was an unhandled error:
                ' enumerate the stack frames of the callstack, and build a text string for display purposes...
                Dim callStackInfo As String
                Dim StackFrame As ErrorStackFrame
                For Each StackFrame In ErrEx.Callstack
                    callStackInfo &= vbCrLf & "> " & StackFrame.ProjectName & "." & StackFrame.ModuleName & "." & StackFrame.ProcedureName
                Next
                
                MsgBox "Run-time error '" & ErrEx.Number & "'" & vbCrLf & vbCrLf & _
                        ErrEx.Description & vbCrLf & vbCrLf & _
                        "Callstack: " & _
                        callStackInfo, vbExclamation
                        
                ' We need to tell the runtime how to deal with this error.
                ' As it was an unhandled error, we just want to 'End'
                ' only other supported value right now is OnErrorResumeNext
                ErrEx.State = OnErrorEnd
        End Select
    End Sub

If you want this to work also in built executables, not just debugging, you need to set the project setting of "Compilation: Include Procedure Name Symbols In Built Executables" to YES.

Once you've called SetThreadGlobalErrorTrap, your global error trap is active for that thread.  For now that means that unhandled errors (i.e. those that are not caught by local error handlers) will trigger your defined GlobalErrorTrap routine to be called.  From within that procedure, you can then enumerate the callstack information, and see (and change) the error handling state.

For more information on how we work with the global error trap, see the documentation from the VBA/VB6 version of vbWatchdog (https://www.everythingaccess.com/vbwatchdog/errex.htm)

In the above example, if you compile with commenting out the SetThreadGLobalErrorTrap call, you get:

With the call SetThreadGlobalErrorTrap, you then get:

Those of you that know the traditional version of vbWatchdog will know that this only scratches the surface, but this initial work at integrating vbWatchdog is an important first step to greater things 🙂

Using this feature in ActiveX controls can be particularly useful, since you can often get an unhandled "shutdown" message from deep within the ActiveX runtime code in tB.  By assigning a global error trap in this way, you can determine where exactly the unhandled error is occurring (e.g. inside ActiveXExtender / UserControl etc), that you can include in your tB bug reports.

[/end WaynePhillipsEA]


Discord Chat Summary

* Auto-generated via Claude-2-100k on poe.com

twinBASIC Development Updates - Week of 10/14

twinBASIC is an open source project to create a modern successor to Visual Basic 6. The Discord server features active discussions around its ongoing development. Here are some highlights from the past week:

  • New project references UI released in Beta 408, with improvements to naming based on feedback
  • Discussion around best practices for naming textbox hint properties
  • Feedback on type library import issues, planned improvements to come
  • BSPrinter confirmed working as drop-in Printer replacement, source shared with twinBASIC developer to aid native implementation
  • Call for help testing and reporting bugs from VB6 developers, including info on providing minimal repro cases
  • Alignment bug in contiguous UDT arrays fixed in Beta 412
  • Long-standing form editor issue resolved in Beta 414, just a one character fix!
  • NESEmulator author active again, project shared for testing NES emulation capabilities

Overall, much progress made on improvements to the UI and bug fixing. The community continues to provide valuable feedback and testing support. As twinBASIC nears version 1.0, there is an ongoing focus on stability and finishing up implementation of VB6 compatibility features. The project maintains strong momentum thanks to the efforts of contributors and the leadership of @WaynePhillipsEA.

Around the Web

CheckBitness Utility from fafalone

Ever have a .dll file sitting around and you weren't sure whether it was compiled to run in a 32-bit environment or a 64-bit environment?  With fafalone's latest project, you can feed that file to a simple user interface and find out what processor architecture the file was compiled for.

Here's fafalone's intro from the GitHub CheckBitness project readme:


CheckBitness

A simple utility to verify an executable is valid and check whether 32bit/64bit

Since twinBASIC supports 64bit, there's more of a reason than ever to check whether an exe or dll is 32bit or 64bit. I was playing around with PE file headers the past few days and decide to turn this into a little demo. There's not much to it, just pick a file, and it tells you if it's 32bit, 64bit AMD64, 64bit IA64, or 64bit ARM64 (for newer Windows on ARM devices); or lets you know if there's a different signature or it couldn't process the file at all.


GitHub - fafalone/CheckBitness: A simple utility to verify an executable is valid and check whether 32bit/64bit
A simple utility to verify an executable is valid and check whether 32bit/64bit - GitHub - fafalone/CheckBitness: A simple utility to verify an executable is valid and check whether 32bit/64bit
-

OSInfo v1.15 Universal Compatibility Version

Another project ported to twinBASIC from fafalone:

VBForums regular Dragokas kindly gave me permission to make an updated version of his OSInfo class, which provides detailed information about the OS and current user. The update makes it compatible across the entire VBx/tB spectrum: VB6, VBA6, VBA7 32bit, VBA7 64bit, and of course, twinBASIC 32bit and twinBASIC 64bit

Dragokas posted the original VB6 project to VBForums here: OS Version information class.

GitHub - fafalone/OSInfo: Universal compatibility version of OSInfo 1.15
Universal compatibility version of OSInfo 1.15. Contribute to fafalone/OSInfo development by creating an account on GitHub.

StackOverflow Q&A: Direct assembly code execution in VBA - only fails in Excel

Greedo recently posted a question about a low-level memory-swapping technique that works in twinBASIC but crashes VBA.  

Here's an excerpt from his question:

I have some VBA code to swap one of the function pointers in a COM vtable with a NO-OP bit of assembly code. It works in twinBASIC which is a standalone VBA environment, so I know I'm very close, however in Excel it crashes.

The question and answer are both a bit over my head, but if you know a bit about virtual tables in COM and are interested in how VBA "compiles" to p-code, you will likely find the short discussion worth your time.

Changelog

Here are the updates from the past week.  You can also find this information by visiting the GitHub twinBASIC Releases page.

Releases · WaynePhillipsEA/twinbasic
Contribute to WaynePhillipsEA/twinbasic development by creating an account on GitHub.

ChatGPT Changelog Summary

* Auto-generated via ChatGPT, sorted in order of ChatGPT's opinion of "most impactful changes."

Based on the changelog provided, here are the key updates in twinBASIC:

  • Added TextBox.TextHintWhenFocused Property: This feature adds a new boolean property to the TextBox control, providing developers with more flexibility in managing text hints. However, to enhance clarity, the property was later renamed to TextHintAlways.
  • Reworked Project References UI: The Integrated Development Environment (IDE) underwent a significant redesign, particularly in the Project References user interface. This redesign aimed to improve the user experience and workflow.
  • Support for [DllExport] Attribute: This update added support for the [DllExport] attribute on module constants, enabling developers to export constants from a DLL, thereby enhancing the language's interoperability capabilities.
  • Provisional vbWatchdog Integration: Several methods and settings were added for provisional and experimental integration with vbWatchdog. This includes the addition of the [_HiddenModule].SetThreadGlobalErrorTrap method and a temporary project setting for including procedure name symbols in built executables.
  • Improved Error Handling and Debugging Stability: Several fixes were applied to improve the stability of the debugger and enhance error handling in internal Class methods. These improvements should lead to a more reliable and user-friendly debugging experience.

Please note that this summary omits some minor bug fixes and focuses on the most impactful changes.


WARNING: The following issue is present in BETA builds 202 - 3xx (the latest build as of publication):

  • there are known memory leaks in these versions, so memory usage will be higher than normal

BETA 408

  • fixed: (addin extensibility) internal ChangedActiveEditor event optimization could crash on x64 at runtime if the event has not been implemented by the Addin [ sokinkeso, discord ]
  • added: TextBox.TextHintWhenFocused boolean property, default False [ sokinkeso, discord ]
  • improved: (IDE) initial redesign of Project References UI

BETA 409

  • changed: TextBox.TextHintWhenFocused renamed to TextHintAlways for clarity [ Krool, discord ]

BETA 410

  • fixed: (regression since BETA 408) Project References list would not automatically appear when a reference was unable to be loaded, after importing a VBP
  • fixed: issue accessing members of the Collection class when exposed from a VB6 DLL [ nextKast, discord ]

BETA 411

  • fixed: (regression) Form.BorderStyle of vbFixedSingle was showing min/max buttons [ https://github.com//issues/1268 ]
  • fixed: some internal Class method error handling issues [ https://github.com//issues/464 ]
  • added: [_HiddenModule].SetThreadGlobalErrorTrap method for provisional and experimental vbWatchdog integration [ see discord for info ]
  • added: (TEMPORARY) project setting 'Compilation: Include Procedure Name Symbols In Built Executables' (default OFF) for use with vbWatchdog runtime callstack iteration [ see discord for info ]
  • fixed: some debugger crashes when IDE evaluates variables of type interface (e.g. in Variables window)

BETA 412

  • fixed: x64 alignment padding of contigious arrays in UDTs defined internally

BETA 413

  • added: support for [DllExport] attribute on module constants [ fafalone, discord ]

BETA 414

  • fixed: Reset statement resolving to account for local procedure shadowing [ fafalone, discord ]