How can my code find out if it's running as VBScript, .HTA, or VBA?

  • A+
Category:Languages

Edit: Most responses so far involve checking for possibly non-existent objects, which outright does not work in VBA with Option Explicit on (it throws a compile-time error, so On Error doesn't work, and turning off Option Explicit is not an option). Is there some other roundabout / out-of-the-box way to find out what's needed here?

I'm trying to write generic copy-and-paste code that will work in a standalone VBScript (a .vbs file), in a .hta file, and as VBA (for instance, in an Excel file). To do that, I need some way for the code itself to tell what engine it's running in.

The best idea I've heard so far involved testing if certain objects exist or not, but in VBA, that fails at compile time (so I can't bypass it with On Error), so that didn't work out. Trying to find out the name of the file it's running didn't end up being viable; that's one of the things that's done differently depending on which of the three script engines the code's running in. I would love to have something simple like this, but am not sure what to fill it in with:

Option Explicit  '--- Returns a string containing which script engine this is running in, '--- either "VBScript", "VBA", or "HTA".  Function ScriptEngine()      If {what goes here?} Then ScriptEngine="VBS"     If {what goes here?} Then ScriptEngine="VBA"     If {what goes here?} Then ScriptEngine="HTA"     End Function 

If this is filled in right, you should be able to copy and paste that function into any VBA, VBS, or HTA file without modification, call it, and get a result instead of an error, even when Option Explicit is on. What's the best way to go about this?

 


The restriction on requiring Option Explicit in the VBA implementation makes this a little more difficult than it otherwise would be (it's a one-liner without it)... Ironically it also turns out to be the key to the solution. If you don't limit yourself to a single function, you can get away with it by doing something like this:

Dim hta  Sub window_onload()      hta = True End Sub  Function HostType()     On Error Resume Next     If hta Then         HostType = "HTA"     Else         Dim foo         Set foo = foo         If Err.Number = 13 Then             HostType = "VBA"         Else             HostType = "VBS"         End If     End If End Function 

It works like this - If it's loaded via an HTA file, the window_onload event handler runs, setting the hta variable to True. That's the first test. The second "test" is on the error thrown by the line Set foo = foo. This is a type mismatch in VBA, where it is interpreted as trying to Set a Variant to Empty, which isn't a compatible type. The same line of code throws an error 424 (Object required) in VBScript because it is not a strongly typed language. That means VBA's type check is skipped and it attempts to actually perform the assignment (which fails). The rest is just figuring out how it threw and returning the result.

Test code

VBA

Option Explicit  Dim hta  Sub Test()     Debug.Print HostType    'VBA End Sub  Sub window_onload()      hta = True End Sub  Function HostType()     On Error Resume Next     If hta Then         HostType = "HTA"     Else         Dim foo         Set foo = foo         If Err.Number = 13 Then             HostType = "VBA"         Else             HostType = "VBS"         End If     End If End Function 

VBScript

WSCript.Echo HostType  Dim hta  Sub window_onload()      hta = True End Sub  Function HostType()     On Error Resume Next     If hta Then         HostType = "HTA"     Else         Dim foo         Set foo = foo         If Err.Number = 13 Then             HostType = "VBA"         Else             HostType = "VBS"         End If     End If End Function 

HTA

<HTML>     <BODY>         <script type="text/vbscript">             Dim hta              Sub Test()                 MsgBox HostType              End Sub              Sub window_onload()                  hta = True             End Sub              Function HostType()                 On Error Resume Next                 If hta Then                     HostType = "HTA"                 Else                     Dim foo                     Set foo = foo                     If Err.Number = 13 Then                         HostType = "VBA"                     Else                         HostType = "VBS"                     End If                 End If             End Function         </script>         <button onclick="vbscript:Test()">Click me</button>      </BODY> </HTML> 

EDIT:

FWIW, the one-liner referenced above if Option Explicit isn't needed is simply this:

Function HostString()     HostString = Application & document & WScript End Function 

All three objects have a default property that returns a String. In VBScript, this will return "Windows Script Host". In VBA, it will return the name of the host (i.e. "Microsoft Excel" in Excel). In HTA it will return "[object]".

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: