twinBASIC Update: May 9, 2021

Highlights include support for a new Attribute syntax, ActiveX DLL registration via regsvr32, and PredeclaredID for twinBASIC classes.

twinBASIC Update: May 9, 2021

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.


Attribute Support

As of version 0.9.2648, twinBASIC added support for attributes using a square-bracket syntax.  The following attributes are currently supported:

  • Description
  • DispId
  • DefaultMember
  • Enumerator
  • UseGetLastError
  • PredeclaredId

Here's a screenshot of the new feature in action:

DllRegisterServer support

As of version 0.9.2443, twinBASIC added support for DllRegisterServer and DllUnregisterServer.  With this update, you can now build ActiveX DLLs with twinBASIC and distribute them to machines.  Previously, ActiveX DLLs had to be registered using the VS Code IDE, which meant they could only run on the development machine.

This is the feature that allows you to use regsvr32 to register your ActiveX DLL in the Windows registry so that you can call it from VBA.  For example:

Registering a twinBASIC ActiveX DLL.
Un-registering a twinBASIC ActiveX DLL.

There are a couple of really nice features to go along with this functionality.

Choice of HKLM vs. HKCU

By default, twinBASIC will register the ActiveX DLL in the user registry hive (HKCU).  This is important, because it means that registering the library will NOT require admin privileges.  

If you need to install your libary machine-wide, that's still an option.  There's an option in the Settings file to do that:

ActiveX DLLs can be registered to HKCU or HKLM.

Note that if you want to register to HKLM (VB6's behavior), you'll probably want to run VS Code as an administrator to make debugging simpler.

Custom registrations

There is also an option to run custom twinBASIC code during the register and unregister process.  This code runs in addition to the standard registration and unregistration code.

The custom DllRegisterServer function runs after the normal registration code.  So the custom code is only called if the initial registration succeeds.  Unregistration works in reverse.  The custom DllUnregisterServer function is called before the normal unregistration code.  

Returning False from the DllUnregisterServer function will prevent the normal unregistration code from running.

Your two cents

There is an active discussion around this feature at the Github project page: Generated ActiveX DLLs need to support DllRegisterServer and DllUnregisterServer.  If you have thoughts on how you want to see this feature implemented, particularly around the exact behavior of the HKLM vs. HKCU registration/unregistration, pop over to GitHub and join the conversation.

PredeclaredId attribute support

As of version 0.9.2648, twinBASIC added support for predeclared twinBASIC classes.  If you set a class attribute of PredeclaredID to a twinBASIC class, then twinBASIC will create a default instance of that class using the class's name.

For example, let's say we have a class named App.  Normally, to use that class, we would first need to create an object variable of type and then set that variable to a new instance of the App class.  With a PredeclaredID, we can use a default instance of that class without creating a separate object variable.

This functionality is available in VBA and VB6, but twinBASIC adds support for a simpler attribute syntax (the existing syntax is still supported for backward compatibility).  The new twinBASIC syntax for this is [PredeclaredID].  That line goes directly above the line that creates the class module.

Here's an example:

For a class with a PredeclaredID, twinBASIC provides us with a default instance.


Here are the updates from the past week.  You can also find this information by installing the twinBASIC VS Code extension and clicking on the Changelog tab of the extension page:

[v0.9.2699, 9th May 2021]

[v0.9.2651, 8th May 2021]

[v0.9.2649, 8th May 2021]

  • fixed: [WithDispatchForwarding] attribute wasn't actually effective

[v0.9.2648, 8th May 2021]

[v0.9.2617, 7th May 2021]

  • added: implicit compiler conditional argument of 'TWINBASIC' for conditional compilation purposes
  • added: support for attributes using the square-bracket syntax [ ]
  • added: [Description("")] attribute
  • added: [DispId(
  • added: [DefaultMember] attribute for class members [same as DispId(0)]
  • added: [Enumerator] attribute for class members [same as DispId(-4)]
  • added: [UseGetLastError(False)] attribute for Declare statements to avoid the implicit call to GetLastError at API call sites

[v0.9.2451, 6th May 2021]

  • fixed: Settings / Build confirugation editor not showing in v1.52 of vscode

[v0.9.2450, 5th May 2021]

  • fixed: WithEvents event subscriptions when multiple WithEvents fields of the same type are defined in a single class

[v0.9.2443, 5th May 2021]

  • added: implementations of DllRegisterServer and DllUnregisterServer, and tweaked the IDE to use them
  • added: optional callbacks into twinBASIC for procedures named DllRegisterServer and DllUnregisterServer (i.e. Public Sub DllRegisterServer() As Boolean)
  • added: project option: project.dllRegisterLocalMachine (switch between HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE) for DllRegisterServer
  • added: vs code command twinbasic.cleanBuild (F1 > "twinBASIC: clean build (deregister & delete built files)")
  • added: project option project.comThreadingModal (STA/MTA)

[v0.9.2355, 4th May 2021]

[v0.9.2311, 4th May 2021]

[v0.9.2300, 3rd May 2021]

  • fixed: improved handling of data type suffixes at procedure call sites to avoid 'invalid use of datatype hint' errors [ ]
  • fixed: altering a project reference caused other fields in the project settings to keep losing focus
  • fixed: runtime hard-crash when With block was used with a class WithEvents field [ ]
  • fixed: 'implements' matching to procedures prefixed with the type name not always working, e.g. with TKIND_ALIAS types
  • fixed: tB now allows passing variants and strings to byte-array parameters, for supporting DAO.Recordset::Bookmark property-let
  • fixed: implementation of IDispatch::GetIDsOfNames is now case-insensitive
  • fixed: changed the way constant datatypes are handled, so that they are not implicitly Variant when no explicit data type is provided [ ]
  • added: WithDispatchForwarding optional flag to the Implements statement, allowing outer class members to become accessible to a dispatchable implemented interface. [e.g. Implements IRibbonExtensibility WithDispatchForwarding]

All original code samples by Mike Wolfe are licensed under CC BY 4.0