Is there any way to list available methods for created object in VBS?
For example:
Set IE = CreateObject(\"InternetExplorer.Application\")
Using TypeLib Information Objects
from tlbinf32.dll
it is possible to list all members of a class.
tlbinf32.dll
was part of Visual Studio 6.0, which was the current release in the years around 2000. Microsoft seems to not offer the DLL for download anymore (situation mid 2017), but you can download it from various sites on the internet. I found version 1.1.88.4, Build 8804, Copyright Matthew Curland 1996, Microsoft 1997-2000, size 148.480 Bytes at https://www.dll4free.com/tlbinf32.dll.html, or other sites.
To install the DLL in Win32, copy it to %windir%\System32
and as administrator call regsvr32.exe tlbinf32.dll
from that directory.
To insttall the DLL in Win64, copy it to %windir%\syswow64
, then as administrator register with %windir%\syswow64\regsvr32.exe
, and finally run the vbscript with %windir%\syswow64\cscript.exe
(or wscript.exe
). Thanks BuvinJ for the hint
The following script demonstrates the included function VariableInfo
which will return a string with the type of the passed variable, and in case of an Object, all members with details, including type of Property
, callable type (Sub
or Function
), and parameter names and return type in case of Function. The type name of the object in case of a COM
object would be the name of the implemented Interface. Not sure if it works for multiple implemented interfaces, but AFAIK it's not possible to implement multiple interfaces in one class via COM
anyway.
It does not support recursion in any way, because this would lead to infinity loops for some types.
This will give you virtually full working reflection in VBS. Great to explore APIs for example with the Microsoft Script Debugger.
' Reflection for VBScript via tlbinfo32.dll
'
' Patrick Strasser-Mikhail 2017-2019
' Ansgar Wiechers 2019
' https://stackoverflow.com/questions/14305750/list-object-methods-and-properties/44459670#44459670
Option Explicit
' Returns a String describing the passed object/variable on the first level, no recursion.
Function VariableInfo(obj)
Const invokeKindPropertyGet = 0
Const invokeKindFunction = 1
Const invokeKindPropertyPut = 2
Const invokeKindPropertyPutRef = 4
If isEmpty(obj) Or _
isNull(obj) _
Then
VariableInfo = TypeNameFromVarType(VarType(obj))
ElseIf Not IsObject(obj) Then
If Not isArray(obj) Then
VariableInfo = TypeNameFromVarType(VarType(obj)) & ", Value: " & obj
Else
VariableInfo = TypeNameFromVarType(VarType(obj)) & "("
Dim dimension
Dim size
On Error Resume Next
Err.Clear
For dimension = 1 To 10 ' deliberate limit to prevent infinite loop
size = Ubound(obj, dimension) + 1
If Err.Number <> 0 Then
Exit For
End If
If dimension > 1 Then
VariableInfo = VariableInfo & ","
End If
VariableInfo = VariableInfo & Ubound(obj, dimension)
Next
On Error Goto 0
VariableInfo = VariableInfo & ")"
End If
ElseIf TypeName(obj) = "Nothing" Then
VariableInfo = "Nothing (The Invalid Object)"
Else
Dim TLI
Dim MemberInfo
Dim TypeInfo
Set TLI = CreateObject("TLI.TLIApplication")
VariableInfo = "Object " & TypeName(obj)
On Error Resume Next
Err.Clear
Set TypeInfo = TLI.InterfaceInfoFromObject(obj)
If Err.Number <> 0 Then
VariableInfo = VariableInfo & "; Error " & Err.Number
VariableInfo = VariableInfo & ": " & Err.Description
Err.Clear
Exit Function
End If
For Each MemberInfo In TypeInfo.Members
Dim Desc
Desc = ""
Select Case MemberInfo.InvokeKind
Case InvokeKindFunction
If MemberInfo.ReturnType.VarType <> 24 Then
Desc = " Function " & TypeNameFromVarType(MemberInfo.ReturnType.VarType)
Else
Desc = " Sub"
End If
Desc = Desc & " " & MemberInfo.Name
Dim ParameterList
ParameterList = Array()
Dim Parameter
For Each Parameter In MemberInfo.Parameters
ReDim Preserve parameterList(UBound(ParameterList) + 1)
ParameterList(Ubound(parameterList)) = Parameter.Name
Next
Desc = Desc & "(" & Join(ParameterList, ", ") & ")"
'Set parameters = Nothing
Case InvokeKindPropertyGet
Desc = " Property " & MemberInfo.Name
Case InvokeKindPropertyPut
Desc = " Property (set/get) " & MemberInfo.Name
Case InvokeKindPropertyPutRef
Desc = " Property (set ref/get) " & MemberInfo.Name
Case Else
Desc = " Unknown member, InvokeKind " & MemberInfo.InvokeKind
End Select
VariableInfo = VariableInfo & vbNewLine & Desc
Next
Set TypeInfo = Nothing
Set TLI = Nothing
End If
End Function
' Decode Type Number to something readable
Function TypeNameFromVarType(typeNr)
Dim typeDetails
set typeDetails = CreateObject("Scripting.Dictionary")
typeDetails.add 0, "vbEmpty (uninitialized variable)"
typeDetails.add 1, "vbNull (value unknown)"
typeDetails.add 2, "vbInteger" ' Short?
typeDetails.add 3, "vbLong" ' Integer?
typeDetails.add 4, "vbSingle"
typeDetails.add 5, "vbDouble"
typeDetails.add 6, "vbCurrency"
typeDetails.add 7, "vbDate"
typeDetails.add 8, "vbString"
typeDetails.add 9, "vbObject"
typeDetails.add 10, "Exception"
typeDetails.add 11, "vbBoolean"
typeDetails.add 12, "vbVariant"
typeDetails.add 13, "DataObject"
typeDetails.add 14, "vbDecimal"
typeDetails.add 17, "vbByte"
typeDetails.add 18, "vbChar"
typeDetails.add 19, "ULong"
typeDetails.add 20, "Long" ' realy Long?
typeDetails.add 24, "(void)"
typeDetails.add 36, "UserDefinedType"
If typeDetails.Exists(typeNr) Then
TypeNameFromVarType = typeDetails(typeNr)
ElseIf typeNr > 8192 Then
TypeNameFromVarType = "vbArray{" & TypeNameFromVarType(typeNr - 8192) & "}"
Else
typeNameFromVarType = "Unknown Type " & typeNr
End If
End Function
' Some nice example class to demonstrate all possible interfaces.
Class MyClass
Dim Name_
Dim Name2_
Public Property Get Name
Name = Name_
End Property
Public Property Let Name(ByVal Value)
Name_ = Value
End Property
Public Property Let Name2(ByRef Value)
Set Name2_ = Value
End Property
Sub TestSub()
WScript.Echo "Test"
End Sub
Sub TestFunc(message)
WScript.Echo "Test: " & message
End Sub
Sub TestFunc2(ByRef message)
WScript.Echo "Test: " & message
End Sub
Function Add(first, second)
Add = first + second
End Function
Function Substract(ByVal first, ByRef second)
Add = first - second
End Function
End Class
Sub testVariableInfo()
Dim variable
' vbEmpty
Wscript.Echo VariableInfo(variable)
variable = Null
Wscript.Echo VariableInfo(variable)
Set variable = Nothing
Wscript.Echo VariableInfo(variable)
Dim MyObject
Set MyObject = new MyClass
Wscript.Echo VariableInfo(MyObject)
Set MyObject = Nothing
Dim TestA1(3, 7)
Wscript.Echo VariableInfo(TestA1)
Dim TestA2()
Wscript.Echo VariableInfo(TestA2)
Dim TestA3
TestA3 = Array(4, 5, 6)
Wscript.Echo VariableInfo(TestA3)
End Sub
testVariableInfo
For for more information about the Typelib Interface, get the documentation help file from Microsoft KB artivle 224331
Matthew Curland offers for download at the website to his book Advanced Visual Basic 6 the nice program Type Library Editor (EditTLBEval.exe) as evaluation version, and the according Documentation
Especially in this context I really like the line If you're a Visual Basic developer who refuses to recognize the commonly accepted limitations of VB, this book is definitely for you. by Ted Pattison. Just replace VB by VBScript here.
VBWebProfi gave the hint for TLI, thanks for that. Working out the details and writing the code was several hours of work, though ;-)