List object methods and properties

2020-02-26 18:53发布

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?

6条回答
该账号已被封号
2楼-- · 2020-02-26 19:22

Use TLI . The TLI.TLIApplication class (from tlbinf32.dll) can inspect various COM objects from their instance. Explore the TLI library in Excel or other Microsoft product that supports scripting and has an script editor which is able to add references, then add tlbinf32.dll. The name in the references is "Typelib information".

Note that the DLL does not ship with Windows, though.

Use the method InterfaceInfoFromObject() for VBScript classes and alternatively try ClassInfoFromObject().

Option Explicit

Dim TLI
Dim MyObject
Dim TypeInfo
Dim MemberInfo

Set TLI = CreateObject("TLI.TLIApplication")
Set MyObject = New MyClass
Set TypeInfo = TLI.InterfaceInfoFromObject(MyObject)

For Each MemberInfo In TypeInfo.Members
    WScript.Echo MemberInfo.Name
Next

Class MyClass
    Dim Name_

    Public Property Get Name
        Name = Name_
    End Property

    Public Property Let Name(ByVal Value)
        Name_ = Value
    End Property
End Class
查看更多
再贱就再见
3楼-- · 2020-02-26 19:29

If you happen to be using HP UFT or QTP then follow these steps:

1) Install any version of MS Visual Studio onto your laptop. (Don't worry about licensing, you won't be running VS)

2) Reboot your computer.

3) Launch UFT or QTP, load a script and hit F11, (or pause at any piece of code that is near the object you want to inspect).

4) Add the object to the Watch window. It can be an Object Repository object or a programmatic description.

If the object exists, the object will now display two Plus (+) signs in the Watch window that can be expanded to show all available Methods and Properties, as well as child objects that can be expanded.

查看更多
戒情不戒烟
4楼-- · 2020-02-26 19:36

While that is partially true, its incomplete.... Google, GetObjectText_, Methods_, & Propeties_

The referenced methods will only work on objects collected while connected to the cimv2 namespace of a remote host via the WbemScripting.SWbemLocator object. If this object has the ability to work on localhost, it's unapparent to me.

Once you do this you can query any of the classes held therein [Win32_Services,Win32_Drives, etc] and interrogate the objects in the resultset using a For-Next loop on the object like below...

For Each oProp in oObject.Properties_
    'be careful here because some propeties may be an object or an array.
    'so test for that here using "typename" or "vartype"
    wScript.Echo oProp.Name & vbTab & oProp
Next

Or...

For Each oMethod in oObject.Methods_
    wScript.Echo oProp.Name
Next

Finally, ...

For Each oProp in oObject.Properties_
   'This will display all of an objects properties
   oProp.GetObjectText_
Next
查看更多
看我几分像从前
5楼-- · 2020-02-26 19:38

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.

查看更多
祖国的老花朵
6楼-- · 2020-02-26 19:40

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 ;-)

查看更多
小情绪 Triste *
7楼-- · 2020-02-26 19:40

Try this ...

For i = 0 To webElementCount-1 Step 1

  innertextProp = myValue2(i).GetROProperty("innertext")
  print i & innertextProp
  print innertextProp

Next
查看更多
登录 后发表回答