Ok, here is a couple of utility functions to load enumerations and constants from type libraries (found in .EXE, .DLL, .TLB and .OLB files).

Unfortunately the process is not all that quick, so this is mostly useful as part of a process to generate a KiXtart include file with all the constants defined.

Also note, it is a bugger to get the typelib file. Where it is available I have simply assumed that the highest Major/Minor version is the current version.

I have included an option which will search for a typelib when it is not explicitly defined. It's slow, but it works.

Finally, for any of this to work you will need the typelib info helper DLL registered. This is tlbinf32.dll, and is an undocumented DLL provided with the MS visual development tools. I believe that it may also be available with Win2000. It is also available from at least two locations on the web, one as a WISE installation.

Microsoft now provide some documentation for the DLL, although it remains unsupported. You can use the DLL to enumerate interfaces and declarations if you wish.

The first function loads the constants enumerations from a named typelib file into a pair of arrays within a parent array. I do it this way as it fits my needs - you could return an array of assignments instead:

Code:
; Pass the name of a file containing typelib information.
; Returns a pair of arrays containing constant name and value
Function GetEnumsFromFile($sFile)
Dim $oTLI, $oTypeLib, $coConstants, $oConstant
Dim $iElement
Dim $asArray[2]
Dim $aTemp

$iElement=0

$oTLI=CreateObject("TLI.TLIApplication")
If @ERROR $GetEnumsFromFile="Cannot create typelib info object - maybe you haven't registered tlbinf32.dll?" Exit @ERROR EndIf

$oTypelib=$oTLI.TypeLibInfoFromFile($sFile)
If @ERROR $GetEnumsFromFile=("Error getting typelib info from file") Exit @ERROR EndIf

For Each $coConstants in $oTypeLib.Constants
For Each $oConstant in $coConstants.members
$iElement=$iElement+1
$aTemp=$asArray[0]
Redim Preserve $aTemp[$iElement]
$asArray[0]=$aTemp
$aTemp=$asArray[1]
Redim Preserve $aTemp[$iElement]
$asArray[1]=$aTemp
$asArray[0][$iElement-1]=$oConstant.name
$asArray[1][$iElement-1]=$oConstant.value
Next
Next

$GetEnumsFromFile=$asArray
Exit 0
EndFunction



The second function attempts to find the fie containing the typelib info from the registry.

If you set the optional search flag then if it doesn't get an answer directly it will perform a serial scan of the typelib subkey:
Code:
; Pass a prog id, optional flag to search typelib if not found directly.
; Returns the filename containing the typelib info
Function GetTypelibFromProdID($sProgID,Optional $bSearch)
Dim $sCLSID,$sTypeLibUID
Dim $iIndexMajor, $iIndexMinor,$sMajor, $sMinor, $sMajorUsed, $sMinorUsed, $sPath
Dim $s

If Not KeyExist("HKEY_CLASSES_ROOT\"+$sProgID) $GetTypelibFromProdID="No such ProgID" Exit 2 EndIf
$sCLSID=ReadValue("HKEY_CLASSES_ROOT"+$sProgID+"\CLSID","")
If Not $sCLSID
$GetTypelibFromProdID="Cannot get CLSID"
If @ERROR Exit @ERROR Else Exit 2 EndIf
EndIf
$sTypeLibUID=ReadValue("HKEY_CLASSES_ROOT\CLSID\"+$sCLSID+"\TypeLib","")
If Not $sTypeLibUID
If $bSearch
; Ok, no direct access - search through type lib
$iIndexMajor=0
$sMajor="HKEY_CLASSES_ROOT\CLSID\"+EnumKey("HKEY_CLASSES_ROOT\CLSID",$iIndexMajor)
While Not @ERROR
If KeyExist($sMajor+"\TypeLib")
If $sProgID=ReadValue($sMajor+"\ProgID","")
OR $sProgID=ReadValue($sMajor+"\VersionIndependentProgID","")
$sTypeLibUID=ReadValue($sMajor+"\Typelib","")
$s=Execute("Exit 259")
EndIf
EndIf
If Not $sTypeLibUID
$iIndexMajor=$iIndexMajor+1
$sMajor="HKEY_CLASSES_ROOT\CLSID\"+EnumKey("HKEY_CLASSES_ROOT\CLSID",$iIndexMajor)
EndIf
Loop
Else
$GetTypelibFromProdID="Cannot get Typelib UID"
If @ERROR Exit @ERROR Else Exit 2 EndIf
EndIf
EndIf
$sTypeLibUID="HKEY_CLASSES_ROOT\TypeLib\"+$sTypeLibUID
; Iterate through all the keys and subkeys, look for a Win32 key
; Assume that the highest version (with a type lib) is the one we should use
$iIndexMajor=0
$sMajor=EnumKey($sTypeLibUID,$iIndexMajor)
While Not @ERROR
$iIndexMinor=0
$sMinor=EnumKey($sTypeLibUID+"\"+$sMajor,$iIndexMinor)
While Not @ERROR
$s=ReadValue($sTypeLibUID+"\"+$sMajor+"\"+$sMinor+"\win32","")
If $s
If CDbl($sMajor)>CDbl($sMajorUsed) OR
($sMajor=$sMajorUsed AND CDbl($sMinor)>CDbl($sMinorUsed))
$sPath=$s
$sMajorUsed=$sMajor
$sMinorUsed=$sMinor
EndIf
EndIf
$iIndexMinor=$iIndexMinor+1
$sMinor=EnumKey($sTypeLibUID+"\"+$sMajor,$iIndexMinor)
Loop
$iIndexMajor=$iIndexMajor+1
$sMajor=EnumKey($sTypeLibUID,$iIndexMajor)
Loop

If $sPath
$GetTypelibFromProdID=$sPath
Exit 0
EndIf

$GetTypelibFromProdID="Cannot find type library"
Exit 2

EndFunction



Ok, some examples.

First, get the enumerations for DirectX 8, and display them all. Note the use of a relative path name:
Code:
"Loading DirectX 8 constants directly from file..."+@CRLF
$ENUMS=GetEnumsFromFile("dx8vb.dll")
If @ERROR
"Error getting DirectX 8 Enums: "+$ENUMS+@CRLF
"Reason: ["+@ERROR+"] "+@SERROR+@CRLF
Else
For $iIndex=0 To UBound($ENUMS[0])
$ENUMS[0][$iIndex]+"="+$ENUMS[1][$iIndex]+@CRLF
If Not(($iIndex+1) mod 20) @CRLF+"Hit return for next page: " GetS $ EndIf
Next
EndIf



Now, get the Excel enumerations via the ProgID (which you would use in CreateObject()), and look up the value for a single constant:
Code:
"Loading Excel document constants via ProgID..."+@CRLF
$sTypeLib=GetTypelibFromProdID("Excel.Sheet",1)
If @ERROR
"Error getting Enums: "+$sTypeLib+@CRLF
"Reason: ["+@ERROR+"] "+@SERROR+@CRLF
Else
$ENUMS=GetEnumsFromFile($sTypeLib)
If @ERROR
"Error getting Excel Enums: "+$ENUMS+@CRLF
"Reason: ["+@ERROR+"] "+@SERROR+@CRLF
Else
"XLButtonOnly="+$ENUMS[1][Ascan($ENUMS[0],"XLButtonOnly")]+@CRLF
EndIf
EndIf