Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Importing constants from a typelib via VBScript

318 views
Skip to first unread message

Alex K. Angelopoulos (MVP)

unread,
Oct 30, 2002, 11:58:05 PM10/30/02
to
I've been fiddling with Michael Harris' typelib extraction HTA (based on using
tlbinf32.dll to extract data), and finally sat down and figured out enough to
approach the idea of doing automatic "luxury object wrapping". By that, I mean
create a procedure such that, given a class name in a classic VBScript, it can
return an object reference to the object and import the enumerations for it as
global constants.

Unfortunately, my approach of using ClassInfoFromObject to eventually get a
TypeLibInfo object will fail for some objects. Notes below

The HTA core script when pared down comes down to roughly this it looks like:

Set TLA = CreateObject("TLI.TLIApplication")
Set TLI = TLA.TypeLibInfoFromFile(filename)

' at this point we can iterate over the enums within TLI's constants collection
' and use ExecuteGlobal with a "constructed" command line

For Each CEnum In TLI.Constants
' We only want them if they are visible
If Left(CEnum.Name, 1)<>"_" Then
For Each Constant In CEnum.Members
ExecuteGlobal "CONST " & Constant.name & "=" & Constant.value
Next
End If
Next


That works perfectly. If I want to instantiate an object, though, and get the
material imported from it, it doesn't always work.

Let's take as examples

Set Sh = CreateObject("WScript.Shell")
Set IE = CreateObject("InternetExplorer.Application")


The only way I can find so far to get a TypeLibInfo object from an instantiated
object is this:

Set TLA = CreateObject("TLI.TLIApplication")
Set TLI = TLA.ClassInfoFromObject(Object).Parent

This works fine against WScript.Shell, but fails for
InternetExplorer.Application. Specifically, I get this when I try to set TLI
for IE:

Error: Class doesn't support Automation
Code: 800A01AE
Source: Microsoft VBScript runtime error

I assume there is a better way to do this. Any ideas?


mayayana

unread,
Oct 31, 2002, 12:43:35 AM10/31/02
to
Microsoft never follows their own rules about anything. If you
follow the class info. in HKCR, "InternetExplorer.Application"
dead-ends, with only a typelib key to follow. The typelib is for
SHDOCVW.DLL. That contains the browser class but the
DOM typelib info. is in MSHTML.TLB. I've found no indication
in the Registry of how MSHTML.TLB connects to IE.App.,
COM-wise. It seems to be a hard-coded specail case.

--
--
Alex K. Angelopoulos (MVP) <a...@mvps.org> wrote in message
news:eGHfLnJgCHA.3556@tkmsftngp08...

Mark_Pryor

unread,
Oct 31, 2002, 2:40:31 AM10/31/02
to
Hi Alex,

On Wed, 30 Oct 2002 23:58:05 -0500, "Alex K. Angelopoulos \(MVP\)"
<a...@mvps.org> wrote:

>I've been fiddling with Michael Harris' typelib extraction HTA (based on using
>tlbinf32.dll to extract data), and finally sat down and figured out enough to
>approach the idea of doing automatic "luxury object wrapping". By that, I mean
>create a procedure such that, given a class name in a classic VBScript, it can
>return an object reference to the object and import the enumerations for it as
>global constants.
>
>Unfortunately, my approach of using ClassInfoFromObject to eventually get a
>TypeLibInfo object will fail for some objects. Notes below
>

>That works perfectly. If I want to instantiate an object, though, and get the


>material imported from it, it doesn't always work.
>
>Let's take as examples
>
>Set Sh = CreateObject("WScript.Shell")
>Set IE = CreateObject("InternetExplorer.Application")
>
>
>The only way I can find so far to get a TypeLibInfo object from an instantiated
>object is this:
>
> Set TLA = CreateObject("TLI.TLIApplication")
> Set TLI = TLA.ClassInfoFromObject(Object).Parent
>
>This works fine against WScript.Shell, but fails for

Use TLIApplication->InterfaceInfoFromObject(Object).Parent

hagd,
Mark

Alex K. Angelopoulos (MVP)

unread,
Oct 31, 2002, 6:21:46 AM10/31/02
to
In news:hcn1su0s9ca02dab3...@4ax.com,
Mark_Pryor typed:
> Hi Alex,

>
> Use TLIApplication->InterfaceInfoFromObject(Object).Parent
>
> hagd,
> Mark

Yep, you're still brilliant Mark. This works exactly....


Set IE = CreateObject("InternetExplorer.Application")

ImportEnumsFromObject IE, True

Sub ImportEnumsFromObject(Object, bDisplay)
' PURPOSE: Imports Typelib constants into global namespace
' Works with any instantiated class supporting automation.
' DEPENDENCY: TLBINF32.DLL must be present and registered
' Derived from Michael Harris' Typelib extraction HTA
' *** Setting bDisplay to True echoes the constants
' instead of importing them.
' WARNING: Some TLBs contain hundreds of constants!
Dim TLA, TLI, CEnum, Constant


Set TLA = CreateObject("TLI.TLIApplication")

Set TLI = TLA.InterfaceInfoFromObject(Object).Parent
For each CENum in TLI.Constants


' We only want them if they are visible
If Left(CEnum.Name, 1)<>"_" Then
For Each Constant In CEnum.Members

If bDisplay Then
WScript.Echo CEnum & ":", Constant.name, "=", Constant.value
Else


ExecuteGlobal "CONST " & Constant.name & "=" & Constant.value

End If
Next
End If
Next
End Sub


==================================================================
==================================================================
==================================================================

Set IE = ImportObject("InternetExplorer.Application")


Function ImportObject(sClass)
' PURPOSE: Given a classname, this function will:
' + return a reference to the object
' + Import Typelib constants into global namespace
' DEPENDENCY: TLBINF32.DLL must be present and registered
' Derived from Michael Harris' Typelib extraction HTA
' WARNING: Some TLBs contain hundreds of constants!
Dim TLA, TLI, CEnum, Constant, Object
Set Object = CreateObject(sClass)


Set TLA = CreateObject("TLI.TLIApplication")

Set TLI = TLA.InterfaceInfoFromObject(Object).Parent
For each CENum in TLI.Constants


' We only want them if they are visible
If Left(CEnum.Name, 1)<>"_" Then
For Each Constant In CEnum.Members
ExecuteGlobal "CONST " & Constant.name & "=" & Constant.value
Next
End If
Next

Set ImportObject = Object
End Function

Paul Randall

unread,
Nov 7, 2002, 4:41:57 PM11/7/02
to
Thanks, Alex

You make it so easy!

I've wanted a quick and easy way to get the info on an application's constants. Code snippets from MSDN and elsewhere so often
neglect to include the necessary constant definitions.

It is amazing what TLBINF32.DLL can do; a copy of its help file is available at:
http://download.microsoft.com/download/vstudio60pro/doc/1/WIN98/EN-US/Tlbinf32.exe
Note that this .exe contains only the zipped Tlbinf32.chm file, which was last modified October, 1998. Does anyone have a newer
version?

-Paul Randall

"Alex K. Angelopoulos (MVP)" <a...@mvps.org> wrote in message news:#90$j9MgCHA.2556@tkmsftngp08...

Alex K. Angelopoulos (MVP)

unread,
Nov 7, 2002, 5:57:26 PM11/7/02
to
That is the latest one I've seen anywhere.

In news:#GpbyZqhCHA.2592@tkmsftngp09, Paul Randall typed:

--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp

Michael Harris (MVP)

unread,
Nov 7, 2002, 8:00:50 PM11/7/02
to
>> Note that this .exe contains only the zipped Tlbinf32.chm file,
>> which was last modified October, 1998. Does anyone have a newer
>> version?


AFAIK, that's as current as they get...


--
Michael Harris
Microsoft.MVP.Scripting
Seattle WA US


Paul Randall

unread,
Nov 21, 2002, 1:58:07 PM11/21/02
to
Alex K. Angelopoulos (MVP) wrote:
>
> Set IE = ImportObject("InternetExplorer.Application")
>
> Function ImportObject(sClass)
> ' PURPOSE: Given a classname, this function will:
> ' + return a reference to the object
> ' + Import Typelib constants into global namespace
> ' DEPENDENCY: TLBINF32.DLL must be present and registered
> ' Derived from Michael Harris' Typelib extraction HTA
> ' WARNING: Some TLBs contain hundreds of constants!
> Dim TLA, TLI, CEnum, Constant, Object
> Set Object = CreateObject(sClass)
> Set TLA = CreateObject("TLI.TLIApplication")
> Set TLI = TLA.InterfaceInfoFromObject(Object).Parent
> For each CENum in TLI.Constants
> ' We only want them if they are visible
> If Left(CEnum.Name, 1)<>"_" Then
> For Each Constant In CEnum.Members
> ExecuteGlobal "CONST " & Constant.name & "=" & Constant.value
> Next
> End If
> Next
> Set ImportObject = Object
> End Function

Hi, Alex

I'm still greatly enjoying this routine.
Maybe I'm enjoying it two much ;-)

What fix would you suggest for when the routine is called a second time for the same typelib, such as:

Set IE1 = ImportObject("InternetExplorer.Application")
Set IE2 = ImportObject("InternetExplorer.Application")

which causes error number 800A0411, Name redefined?

I suppose all redefinitions with the same value as previously defined could be ignored, and redefinitions with different values
could be flagged.

-Paul Randall


Janet Pryor

unread,
Nov 21, 2002, 5:04:49 PM11/21/02
to
Hi Paul,

see inline,

hth,
Mark Pryor (at my Mom's house)
"Paul Randall" <paul...@cableone.net> wrote in message
news:#BBbx$YkCHA.1328@tkmsftngp09...


> Alex K. Angelopoulos (MVP) wrote:
> >
> > Set IE = ImportObject("InternetExplorer.Application")
> >
> > Function ImportObject(sClass)
> > ' PURPOSE: Given a classname, this function will:
> > ' + return a reference to the object
> > ' + Import Typelib constants into global namespace
> > ' DEPENDENCY: TLBINF32.DLL must be present and registered
> > ' Derived from Michael Harris' Typelib extraction HTA
> > ' WARNING: Some TLBs contain hundreds of constants!

on error resume next


> > Dim TLA, TLI, CEnum, Constant, Object
> > Set Object = CreateObject(sClass)
> > Set TLA = CreateObject("TLI.TLIApplication")
> > Set TLI = TLA.InterfaceInfoFromObject(Object).Parent
> > For each CENum in TLI.Constants
> > ' We only want them if they are visible
> > If Left(CEnum.Name, 1)<>"_" Then

err.clear


> > For Each Constant In CEnum.Members
> > ExecuteGlobal "CONST " & Constant.name & "=" & Constant.value

if err.number = &h800A0411 then exit for

Paul Randall

unread,
Nov 21, 2002, 8:41:45 PM11/21/02
to
Janet Pryor wrote:
> Mark Pryor (at my Mom's house)

> if err.number = &h800A0411 then exit

Hi, Mark
Thanks for the quick reply.

I think your mods would work except that with error-checking on, the error number is different - &h0411, or decimal 1041. I had
already edited the routine to make it more understandable to me, and today I did some more to take care of this problem. This is
what I have now, which seems to work well.


'****************************************************************


Function ImportObject(sClass)
' PURPOSE: Given a classname, this function will:
' + return a reference to the object
' + Import Typelib constants into global namespace
' DEPENDENCY: TLBINF32.DLL must be present and registered
' Derived from Michael Harris' Typelib extraction HTA
' WARNING: Some TLBs contain hundreds of constants!

' Alex K. Angelopoulos posted this on 10/31/02.
'
'Sample usage:
'<CODE>
'Set objIE = ImportObject("InternetExplorer.Application")
'</CODE>
'which is identical to the following code lines, except that
' all approximately 80 constants are defined.
'<CODE>
'Set objIE = CreateObject("InternetExplorer.Application")
'CONST CSC_UPDATECOMMANDS = -1
' ... many more CONST statements
'CONST SWFO_COOKIEPASSED = 4
'</CODE>
'
' Edited and modified to allow repeated calls with
' the same class. Paul Randall 11/21/02

Dim objTLIA 'TypeLib Info Application; TLBinf32.dll
Dim objTLII 'TypeLib Interface Info object for the parent of
' the object created from the specified class.
' Contains a collection of enumeration objects
Dim objCEnum 'One of the enumeration objects
' Contains a collection of constant objects
Dim objConstant 'One constant object in the enumeration object
Dim objObject 'The object specified by the class string passed
' to this routine.

'strMsg for obtaining the list of constants and their values
'Dim strMsg 'List of constants and their values
'strMsg = "Typelib constants for: " & sClass & vbcrlf & vbcrlf

Set objObject = CreateObject(sClass)
Set objTLIA = CreateObject("TLI.TLIApplication")
Set objTLII = objTLIA.InterfaceInfoFromObject(objObject).Parent
For Each objCEnum in objTLII.Constants


' We only want them if they are visible

If Left(objCEnum.Name, 1)<>"_" Then
' strMsg = strMsg & "EnumName: " & objCEnum.Name & _
' " contains " & objCEnum.Members.count & " items." & vbcrlf
For Each objConstant In objCEnum.Members
' strMsg = strMsg & objConstant.name & " = " & objConstant.value & vbcrlf
On Error Resume Next
ExecuteGlobal "CONST " & objConstant.Name & "=" & objConstant.Value
if Err.Number = 1041 then
if eval(objConstant.Name & "=" & objConstant.Value) then
'Ignore unchanged values
else
MsgBox "Unexpected new value for TypeLib constant" & vbcrlf & _
"in Function ImportObject(" & sClass & ")" & vbcrlf & _
"Constant name = " & objConstant.Name & vbcrlf & _
"Old value = " & eval(objConstant.Name) & vbcrlf & _
"New value = " & objConstant.Value & vbcrlf & _
vbcrlf & "Quitting"
WScript.Quit
end if
elseif Err.Number <> 0 then
MsgBox "Unexpected error in " & _
"Function ImportObject(" & sClass & ")" & vbcrlf & _
"Error Number = " & Err.Number & vbcrlf & _
"Error Description = " & Err.Description & vbcrlf & _
"Error Source = " & Err.Source & vbcrlf & _
vbcrlf & "Quitting"
WScript.Quit
end if
On Error GoTo 0
Next
else
' strMsg = strMsg & "EnumName: " & objCEnum.Name & _
' " contains " & objCEnum.Members.count & " hidden items." & vbcrlf
End If
Next
'logmsg1 "LogFile.txt", strMsg
Set ImportObject = objObject
End Function


Alex K. Angelopoulos (MVP)

unread,
Nov 22, 2002, 8:15:37 AM11/22/02
to
Interesting. You know, I had never even considered that issue; it's a good
point, and raises some "bigger" questions involving the state of objects and
their namespaces.

One pseudo-eccentricity here is that all of those constants should _probably_ be
imported as properties of a pseudo-class; but this could cause them to be
imported multiple times, cluttering memory and slowing down the script....


--
Please respond in the newsgroup so everyone may benefit.
http://dev.remotenetworktechnology.com
----------
Subscribe to Microsoft's Security Bulletins:
http://www.microsoft.com/technet/security/bulletin/notify.asp

------
I'd like to change the world, but they won't give me the source code.
- Kees Couprie


"Paul Randall" <paul...@cableone.net> wrote in message

news:uYOEXhckCHA.2692@tkmsftngp08...

0 new messages