Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List object methods and properties

Tags:

Is there any way to list available methods for created object in VBS?

For example:

Set IE = CreateObject("InternetExplorer.Application") 

I want to list available properties of this object, as:

IE.AddressBar IE.Application IE.Busy ... 

or methods:

IE.ClientToWindow IE.ExecWB IE.GetProperty ... 

How can I discover available properties to arbitrary valid object in VBS?

like image 332
theta Avatar asked Jan 13 '13 16:01

theta


People also ask

What are objects properties and methods?

An object is a collection of properties, and a property is an association between a name (or key) and a value. A property's value can be a function, in which case the property is known as a method. In addition to objects that are predefined in the browser, you can define your own objects.

What are the methods of an object?

a method is an action which an object is able to perform. sending a message to an object means asking the object to execute or invoke one of its methods.

What are the properties of an object?

The basic properties of an object are those items identified by its four-part name (name, type, instance, and version) and also include owner, status, platform, and release.

How do you list all properties of an object?

To get all own properties of an object in JavaScript, you can use the Object. getOwnPropertyNames() method. This method returns an array containing all the names of the enumerable and non-enumerable own properties found directly on the object passed in as an argument. The Object.

What is the difference between a method and a property?

Using a method causes something to happen to an object, while using a property returns information about the object or causes a quality about the object to change. Most objects are returned by returning a single object from the collection.

What are the properties of an object?

A property is an attribute of an object or an aspect of its behavior. For example, properties of a document include its name, its content, and its save status, and whether change tracking is turned on. To change the characteristics of an object, you change the values of its properties. To set the value of a property,...

How to see an object’s properties and methods in PowerShell?

Use Get-Member to see an object’s properties and methods. The Get-Member cmdlet is used to definitively show us a PowerShell object’s defined properties and methods. We use it by piping the output from our Get-Service cmdlet into Get-Member.

What are methods?

What are Methods? Methods are the actions that can be performed by an an Objects or on an Object. In the above Hose example, paintaing is a Method, building a new room is a method. Similarly, if you want to select a range, you need Select method.


2 Answers

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](/users/3220983/buvinj) for the [hint](/questions/14305750/list-object-methods-and-properties/44459670?noredirect=1#comment86169321_44459670)

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-2021 ' Ansgar Wiechers 2019 ' https://stackoverflow.com/questions/14305750/list-object-methods-and-properties/44459670#44459670 ' ' v1.1 2021-02-01: Show values of arrays and objects, but only one level   ' Returns a String describing the passed object/variable on the first level, ' no recursion. Function VariableInfo(obj)     VariableInfo = VariableInfoToLevel(obj, 0, 1) End Function  ' Returns a String describing the passed object/variable on the first level, ' recurse down to level max_level(0=no recursion). Function VariableInfoToLevel(obj, level, max_level)     Const invokeKindPropertyGet = 0     ' simple data member     Const invokeKindFunction = 1        ' method: Sub or Function     Const invokeKindPropertyPut = 2     ' Docs: has a value setter; reality: more like is settable     Const invokeKindPropertyPutRef = 4  ' Docs: has a reference setter; reality: more like is not settable      If level > max_level Then         VariableInfoToLevel = ""         Exit Function     End If      Dim indent : indent = Space(4 * level)     VariableInfoToLevel = indent      If isEmpty(obj) Or _        isNull(obj) _     Then         VariableInfoToLevel = VariableInfoToLevel & TypeNameFromVarType(VarType(obj))     ElseIf Not IsObject(obj) Then         If Not isArray(obj) Then             VariableInfoToLevel = indent & TypeNameFromVarType(VarType(obj)) & ", Value: [" & obj & "]"         Else             VariableInfoToLevel = indent & TypeNameFromVarType(VarType(obj))             Dim dimension             ReDim sizes(0)             Dim size              On Error Resume Next             Err.Clear              For dimension = 0 To 10 ' deliberate limit to prevent infinite loop                 size = Ubound(obj, dimension + 1)                 If Err.Number <> 0 Then                     ' report ther then Index out of Bounds                     If Err.Number <> 9 Then                          WScript.Echo "Exception " & Err.Number & ": " & Err.Description & "; in " & Err.Source                     End If                     Exit For                 End If                 ReDim Preserve sizes(dimension)                 sizes(dimension) = size               Next             On Error Goto 0              VariableInfoToLevel = VariableInfoToLevel & "(" & Join(sizes, ",") & ")"             Select Case dimension               Case 1                 VariableInfoToLevel = VariableInfoToLevel & " {"  & vbCrlf                 Dim idx                 For idx = LBound(obj) To UBound(obj)                     VariableInfoToLevel = VariableInfoToLevel & indent & _                         "     " & idx & ":" & _                         Trim(VariableInfoToLevel(obj(idx), level + 1, max_level)) & vbCrlf                 Next                  VariableInfoToLevel = VariableInfoToLevel & indent & "}" & vbCrlf                                Case 2                 VariableInfoToLevel = indent & "{" & vbCrlf                  Dim idx1, idx2                 For idx1 = LBound(obj, 1) To UBound(obj, 1)                     For idx2 = LBound(obj, 2) To UBound(obj, 2)                         VariableInfoToLevel = VariableInfoToLevel & indent & _                             "     " & idx1 & "," & idx2 & ":" & _                             Trim(VariableInfoToLevel(obj(idx1, idx2), level + 1, max_level)) & vbCrlf                     Next                 Next                  VariableInfoToLevel = VariableInfoToLevel & indent & "    }" & vbCrlf                              Case Else                 ' 0 is empty anyway, more is too complicated to print, just leave it for now             End Select         End If     ElseIf TypeName(obj) = "Nothing" Then         VariableInfoToLevel = indent & "Nothing (The Invalid Object)"     Else         ' Object         VariableInfoToLevel = indent & "Object " & TypeName(obj)         '' Need to think about that... True for Err, but not for System.Dictionary         '' Seems Err is very special, and we should compare explicitly with internal/predifined Objects (Err, WScript)         'If varType(obj) <> vbObject Then             ' hm, interresting...         '   VariableInfoToLevel = VariableInfoToLevel & " with default property (no analysis possible)"         '   Exit Function         'End If                      Dim TLI         Dim MemberInfo         Dim TypeInfo         Set TLI = CreateObject("TLI.TLIApplication")         VariableInfoToLevel = indent & "Object " & TypeName(obj)          On Error Resume Next         Err.Clear         Set TypeInfo = TLI.InterfaceInfoFromObject(obj)                  If Err.Number <> 0 Then                          VariableInfoToLevel = VariableInfoToLevel & "; Error " & Err.Number             VariableInfoToLevel = VariableInfoToLevel & ": " & Err.Description             Err.Clear             On Error Goto 0             Exit Function         End If         On Error Goto 0                           For Each MemberInfo In TypeInfo.Members             Dim Desc             Dim printNextLevel : printNextLevel = vbFalse             Desc = ""             ' based on .Net System.Runtime.IteropService.ComTypes             '' FIXME: Call by Value/Reference and settable seems to be switched some             '' InvokeKind seems to not encode value passing, rather settable/not settable             '' Needs more work to decode byValue/byReference             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 = "  Data Member " & MemberInfo.Name                     printNextLevel = vbTrue                 Case InvokeKindPropertyPut                     ' Seems to be                      Desc = "  Property " & MemberInfo.Name & " [set by val"                     If IsGettable(obj, MemberInfo.Name) Then                          Desc = Desc & "/get"                         printNextLevel = vbTrue                     End If                     Desc = Desc & "]"                     'Stop                 Case InvokeKindPropertyPutRef                     'Stop                     Desc = "  Property " & MemberInfo.Name & " [set by ref"                     If IsGettable(obj, MemberInfo.Name) Then                          Desc = Desc & "/get"                         printNextLevel = vbTrue                     End If                     Desc = Desc & "]"                     'Stop                 Case Else                     Desc = "  Unknown member, InvokeKind " & MemberInfo.InvokeKind             End Select             VariableInfoToLevel = VariableInfoToLevel & vbNewLine & _                                   indent & Desc             If printNextLevel And level < max_level Then                 VariableInfoToLevel = VariableInfoToLevel & vbNewLine & _                     VariableInfoToLevel(eval("obj." & MemberInfo.Name), level + 1, max_level)             End If         Next          Set TypeInfo = Nothing         Set TLI = Nothing     End If End Function  Function IsGettable(obj, memberName)     Dim value     On Error Resume Next     Err.Clear     value = eval("obj." & memberName)     Stop     If Err.Number <> 0 And _        Err.Number <> 438 And _        Err.Number <> 450 Then         WScript.Echo Err.Number & ": " & Err.Description     End If          '438: Object doesn't support this property or method     '450: Wrong number of arguments or invalid property assignment     If Err.Number = 438 Or _        Err.Number = 450 Then         IsGettable = vbFalse     Else         IsGettable = vbTrue     End If      End Function  Function IsSimpleType(obj)     If (isEmpty(obj) Or isNull(obj)) And (Not IsObject(obj)) And (Not isArray(obj)) Then         IsSimpleType = vbTrue     Else         IsSimpleType = vbFalse     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_     Dim Name3_     Dim Name4_     Dim dict      Private Sub Class_Initialize()         Name_ = "foo"         Name2_ = "bar"         Name3_ = "baz"         Name4_ = "spam"         Set dict = CreateObject("Scripting.Dictionary")     End Sub          Private Sub Class_Terminate()         Set dict = Nothing     End Sub              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      Public Property Get Name3       Name3 = Name3_     End Property      Public Property Set Name3(ByVal Value)       Set Name3_ = Value     End Property      Public Property Get Name4       Name4 = Name4_     End Property      Public Property Set Name4(ByRef Value)       Set Name4_ = 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)      Wscript.Echo VariableInfo(Int(23))     Wscript.Echo VariableInfo(cLng(23))     Wscript.Echo VariableInfo(2147483647)     Wscript.Echo VariableInfo(5/4)     Wscript.Echo VariableInfo(4 * Atn(1)) ' Simplest way to pi, not all inverse functions like arcsin are defined.     Wscript.Echo VariableInfo(3.4E38)     Wscript.Echo VariableInfo(CDbl(3.4E38))     Wscript.Echo VariableInfo(cCur(20.123456))     Wscript.Echo VariableInfo(now)     Wscript.Echo VariableInfo("Some Text")     Wscript.Echo VariableInfo(Err)          Dim MyObject     Set MyObject = new MyClass     Wscript.Echo VariableInfo(MyObject)     Set MyObject = Nothing      Dim TestAEmpty()     Wscript.Echo VariableInfo(TestAEmpty)      ReDim TestA1(17)     Wscript.Echo VariableInfo(TestA1)      Dim TestA2(3, 7)     Wscript.Echo VariableInfo(TestA2)         Dim TestA3     TestA3 = Array(4, 5, 6)     Wscript.Echo VariableInfo(TestA3)      Dim dict     Set dict = CreateObject("Scripting.Dictionary")     WScript.Echo VariableInfo(dict)     Set dict = Nothing 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 ;-)

like image 127
trapicki Avatar answered Oct 02 '22 23:10

trapicki


VBScript itself does not support type introspection outside the TypeName and VarType functions, which will give you the type of an object, but won't give you access to its internal structure.

As other answers explained there is a DLL that would provide this feature, but it doesn't ship with Windows, and since it was part of an old version of Visual Studio there might not be a legal way to obtain it nowadays.

like image 32
Ansgar Wiechers Avatar answered Oct 02 '22 22:10

Ansgar Wiechers