-
Jan 30th, 2015, 09:52 PM
#1
Thread Starter
Hyperactive Member
[RESOLVED] How to find the correct ProgID to use with CreateObject Function?
There are two ways to use Regular Expression from VBScript:
One is to reference to "Microsoft VBScript Regular Expression 5.5"
The other, use CreateObject("VBScript.RegExp")
OK, it is because I know the ProgID of the regular expression, so I can use the CreateObject function. What if I don't know the ProgID? So then how should I find it? And as I see there are two versions of RegExp there, what if I want to use a particular version?
P.S CLSID is also applicable to CreateObject function?
Last edited by bPrice; Jan 30th, 2015 at 09:57 PM.
-
Jan 31st, 2015, 11:07 AM
#2
Re: How to find the correct ProgID to use with CreateObject Function?
You can't directly make use of CLSID values in VB6. They get used under the covers when you have a reference set, but you cannot use them with CreateObject() calls and normally you'd never have a reason to.
In VBScript RegExp is an intrinsic class you can create instances of using Set x = New RegExp. This will get you the class implementing the 5.5 interface, since the ancient 1.0 interface is only around for backward compatibility with very early days.
So don't bother with the 1.0 interface, which was even more quirky than the current one (5.5). The strange numbering comes from the way Microsoft tried to realign script engine and scripting component versions with IE versions when they went to 2.0, which got numbered as 5.5 instead to match IE 5.5. This of course fell apart once they realized how interface version numbering is really meant to work, or perhaps it was an accident caused by some Marketing clown sticking his oar in where it did not belong. In any case there is no "newer version" even though other scripting components moved on to 5.6, 5.7, 5.8, etc. over time.
I don't think modern versions of Windows even have a version dependent ProgID for late-binding 1.0 anymore, if they ever did. Just set a reference to the 5.5 typelib and call it good, there is no reason to do otherwise in a VB6 program. You don't want to use CreateObject() calls here.
-
Jan 31st, 2015, 11:34 AM
#3
Re: How to find the correct ProgID to use with CreateObject Function?
Originally Posted by bPrice
There are two ways to use Regular Expression from VBScript:
One is to reference to "Microsoft VBScript Regular Expression 5.5"
The other, use CreateObject("VBScript.RegExp")
The former is known as Early Binding while the latter is known as Late Binding. It is generally better to early bind object references.
Originally Posted by bPrice
And as I see there are two versions of RegExp there, what if I want to use a particular version?
Version 1.0 of the Microsoft VBScript Regular Expressions library is obsolete. It is provided only for compatibility.
As shown in the code below, both v1.0 and v5.5 have the same ProgIDs, therefore, you won't be able to specify the lower version if you late bind the RegExp object.
Originally Posted by bPrice
P.S CLSID is also applicable to CreateObject function?
No. The Class parameter of the CreateObject function expects the ProgID only of the ActiveX object.
Originally Posted by bPrice
OK, it is because I know the ProgID of the regular expression, so I can use the CreateObject function. What if I don't know the ProgID? So then how should I find it?
You could hunt for the programmatic identifier (ProgID) in the Registry. Or you could try this routine, which seems to be working correctly as far as I can tell.
Code:
Option Explicit
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Private Declare Function CLSIDFromString Lib "ole32.dll" (ByVal lpsz As Long, ByRef pclsid As Any) As Long
Private Declare Function ProgIDFromCLSID Lib "ole32.dll" (ByRef CLSID As Any, ByRef lplpszProgID As Long) As Long
Private Declare Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long) As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (Optional ByVal pv As Long)
Public Function GetProgIDFromObject(ByVal Obj As Object) As String
Const NOERROR = 0&, S_OK = 0&
Dim lpszProgID As Long, sGUID As String, CLSID As GUID
Dim oClassInfo As CoClassInfo, oInterfaceInfo As InterfaceInfo
With TLIApplication.InterfaceInfoFromObject(Obj) 'Set a reference to TypeLib Information (TLBINF32.DLL)
sGUID = .GUID
For Each oClassInfo In .Parent.CoClasses
For Each oInterfaceInfo In oClassInfo.Interfaces
If StrComp(sGUID, oInterfaceInfo.GUID) = 0 Then
If CLSIDFromString(StrPtr(oClassInfo.GUID), CLSID) = NOERROR Then
If ProgIDFromCLSID(CLSID, lpszProgID) = S_OK Then
SysReAllocString VarPtr(GetProgIDFromObject), lpszProgID
CoTaskMemFree lpszProgID
Exit Function
End If
End If
End If
Next
Next
End With
End Function
Code:
Private Sub Main()
Debug.Print """"; GetProgIDFromObject(New ADODB.Stream); """" '"ADODB.Stream.6.0"
Debug.Print """"; GetProgIDFromObject(New CDO.Message); """" '"CDO.Message.1"
Debug.Print """"; GetProgIDFromObject(New IWshRuntimeLibrary.WshShell); """" '"WScript.Shell.1"
Debug.Print """"; GetProgIDFromObject(New MSHTML.HTMLDocument); """" '"htmlfile"
Debug.Print """"; GetProgIDFromObject(New Scripting.FileSystemObject); """" '"Scripting.FileSystemObject"
Debug.Print """"; GetProgIDFromObject(New IWshRuntimeLibrary.FileSystemObject); """" '"Scripting.FileSystemObject"
Debug.Print """"; GetProgIDFromObject(New SHDocVw.WebBrowser); """" '"Shell.Explorer.1"
Debug.Print """"; GetProgIDFromObject(New Shell32.Shell); """" '"Shell.Application.1"
Debug.Print """"; GetProgIDFromObject(New SpeechLib.SpVoice); """" '"SAPI.SpVoice.1"
Debug.Print """"; GetProgIDFromObject(New stdole.StdFont); """" '"StdFont"
Debug.Print """"; GetProgIDFromObject(New TaskScheduler.TaskScheduler); """" '"Schedule.Service.1"
Debug.Print """"; GetProgIDFromObject(New VBScript_RegExp_10.RegExp); """" '"VBScript.RegExp"
Debug.Print """"; GetProgIDFromObject(New VBScript_RegExp_55.RegExp); """" '"VBScript.RegExp"
Debug.Print """"; GetProgIDFromObject(New WbemScripting.SWbemLocator); """" '"WbemScripting.SWbemLocator.1"
Debug.Print """"; GetProgIDFromObject(New WIA.ImageFile); """" '"WIA.ImageFile.1"
Debug.Print """"; GetProgIDFromObject(New WinHttp.WinHttpRequest); """" '"WinHttp.WinHttpRequest.5.1"
End Sub
You might also want to try other viable solutions, like Schmidt's example here or Microsoft's C++ sample code in their KB article How To Get the CLSID and ProgID of a CoClass from the Type Library in OCX, DLL, and EXE Files.
Note that the ProgID retrieved by the function above oftentimes includes the version number. Many ActiveX objects also registers a VersionIndependentProgID in addition to the ProgID. Whenever possible, you should use the version independent one. Just remove the version number from the returned ProgId and see if it still works.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jan 31st, 2015, 09:00 PM
#4
Thread Starter
Hyperactive Member
Re: How to find the correct ProgID to use with CreateObject Function?
Bonnie:
Your reply is very helpful but code provided doesn't work on my machine. The code here for the GetProgIDFromObject seems to lack several type declarations, i.e. oClassInfo. And the submain looks weird as there are so many semicolons in one single line and is it possible to use New keyword when passing parameters?
The latter problem might be okay but there is definitely missing type declarations.
I will follow the links and read more first.
Regardless of the above, I saw
Code:
Debug.Print """"; GetProgIDFromObject(New VBScript_RegExp_10.RegExp); """" '"VBScript.RegExp"
Debug.Print """"; GetProgIDFromObject(New VBScript_RegExp_55.RegExp); """" '"VBScript.RegExp"
So both 10 and 55 version of RegExp use the same ProgID. How do I know for sure if I get the 55 version of RegExp by CreateObject function.
-
Jan 31st, 2015, 09:13 PM
#5
Thread Starter
Hyperactive Member
Re: How to find the correct ProgID to use with CreateObject Function?
Originally Posted by dilettante
Just set a reference to the 5.5 typelib and call it good, there is no reason to do otherwise in a VB6 program. You don't want to use CreateObject() calls here.
Well actually I'm using VBA for Excel. I wrote several subroutines that make use of RegExp but when I copy and paste them to ther Workbooks, I have to set the reference once again. I do this every time and it's kinda tedious. Right now I've already replaced parts like
Code:
Dim mRX As New RegExp
Dim mMS As MatchCollection
Dim mM As Match
to
Code:
Dim mRX As Object
Set mRX = CreateObject("VBScript.RegExp")
Dim mMS As Object
Dim mM As Object
However, the fact that the ProgID of RegExp doesn't specify which version I am using kinda worries me. I don't want make any mistakes as it involves a lot string replacement.
-
Feb 1st, 2015, 12:10 AM
#6
Re: How to find the correct ProgID to use with CreateObject Function?
Originally Posted by bPrice
... but code provided doesn't work on my machine. The code here for the GetProgIDFromObject seems to lack several type declarations, i.e. oClassInfo.
Uh, did you remember to "Set a reference to TypeLib Information (TLBINF32.DLL)"? The missing object types are declared there.
Originally Posted by bPrice
And the submain looks weird as there are so many semicolons in one single line ...
The semicolons tells the Print method to print multiple expressions on the same line without any intervening character(s). This achieves the same effect as concatenating the (String) expressions.
Originally Posted by bPrice
... and is it possible to use New keyword when passing parameters?
Yes. The New keyword is used for explicitly instantiating a new object (or implicitly, as in the case of As New). It can be used anywhere you want to pass or reference a new object instance. Here are a couple more examples:
Code:
With New Collection
.Add New Collection
End With
Originally Posted by bPrice
How do I know for sure if I get the 55 version of RegExp by CreateObject function.
If you don't get an "Object doesn't support this property or method" error when invoking any class method/property available only on the higher version (such as the Multiline property), then you are definitely not using the older version.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Feb 1st, 2015, 12:15 AM
#7
Re: How to find the correct ProgID to use with CreateObject Function?
Then you are posting in the wrong forum. Try the one for Office macro scripting.
But as it says on MSDN:
When given the version-independent ProgID, the CLSIDFromProgID function returns the CLSID of the current version.
And CreateObject makes use of CLSIDFromProgID.
There are no version-dependent ProgIDs for these two classes so there is little risk of ever creating an instance of the old 1.0 RegExp class using CreateObject calls.
Last edited by dilettante; Feb 1st, 2015 at 01:02 AM.
-
Feb 1st, 2015, 04:30 AM
#8
Thread Starter
Hyperactive Member
Re: How to find the correct ProgID to use with CreateObject Function?
Originally Posted by dilettante
And CreateObject makes use of CLSIDFromProgID.
There are no version-dependent ProgIDs for these two classes so there is little risk of ever creating an instance of the old 1.0 RegExp class using CreateObject calls.
Thank you for the tip
Originally Posted by dilettante
Then you are posting in the wrong forum. Try the one for Office macro scripting.
Come on, don't shove me out of here. I like this Forum And you guys are great. As far as this question concerns, what difference does it make to post the thread elsewhere.
-
Feb 1st, 2015, 04:35 AM
#9
Thread Starter
Hyperactive Member
Re: How to find the correct ProgID to use with CreateObject Function?
Originally Posted by Bonnie West
Uh, did you remember to "Set a reference to TypeLib Information (TLBINF32.DLL)"? The missing object types are declared there.
I was going to rate this post but as it said:
You must spread some Reputation around before giving it to Bonnie West again.
Can't do that too often
-
Feb 1st, 2015, 04:33 PM
#10
Re: How to find the correct ProgID to use with CreateObject Function?
Wrong forum is wrong forum. But the main reason to post in the right place is to help future readers who find the thread by searching, though another important one is that the environments are different enough such a thread can quickly go down a rabbit hole of confusion.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|