Monday 5 February 2018

VBA - ProgID - what is the current version

So a SO question arose about a non-installed version of MSXML2.ServerXMLHTTP. This made me wonder why not poke around in the registry to try and find all instances of MSXML2.ServerXMLHTTP in my registry, the results are given in Appendix A. It showed that version 4 is missing just like for the questioner. The registry sweep shows versions 3.0, 5.0 ,6.0 available.

What is really curious is there is a registry key

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Msxml2.ServerXMLHTTP\CurVer

whose default value is

Msxml2.ServerXMLHTTP.3.0

This means if one writes the following code using late binding and no version in the prog id to instantiate a Msxml2.ServerXMLHTTP then one gets a 3.0 version and not a 6.0 version. The rationale is given in this MSDN blog.

Sub CreateXHR()
    Dim oXHR As Object
    Set oXHR = VBA.CreateObject("Msxml2.ServerXMLHTTP")
End Sub

We can write some code to query the registry to tell us what the non versioned prog id actually returns ...

Sub TestCurVersion()

    Debug.Print CurVersion("Msxml2.ServerXMLHTTP")
    '* for me returns Msxml2.ServerXMLHTTP.3.0
    
    Debug.Print CurVersion("Excel.Application")
    '* for me returns Excel.Application.15
    
End Sub


Function CurVersion(ByVal sClass As String) As String
    Const HKLM As Long = &H80000002
    Dim oWMIReg As Object
    
    Set oWMIReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
             ".\root\default:StdRegProv")
    Dim sReturnString As String
    oWMIReg.GetStringValue HKLM, "SOFTWARE\Classes\" & sClass & "\CurVer", "", sReturnString
    CurVersion = sReturnString
End Function

So unless one wants to rewrite the registry keys to change the current version to version 6.0 then I recommend supplying the string "Msxml2.ServerXMLHTTP.6.0" thus

Sub CreateXHR60()
    Dim oXHR As Object
    Set oXHR = VBA.CreateObject("Msxml2.ServerXMLHTTP.6.0")
End Sub

Simulating the ProgID resolution

With COM the resolution of the ProgID take places by calling CLSIDFromString in OLE32.dll and we can write code to simulate this and then go lookup in the registry


Option Explicit

Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type

Private Declare Function OLE32_CLSIDFromString Lib "OLE32" _
    Alias "CLSIDFromString" (ByVal lpszCLSID As String, pclsid As GUID) As Long
    
Public Function VBA_CLSIDFromString(ByVal sClass As String) As String
    
    Dim rclsid As GUID
    Dim hr As Long
    hr = OLE32_CLSIDFromString(StrConv(sClass, vbUnicode), rclsid)
    If hr <> 0 Then Err.Raise hr

    Dim sHexCLSID As String
    
    sHexCLSID = "{" & PadHex(rclsid.Data1, 8) & "-" & PadHex(rclsid.Data2, 4) & "-" & _
                PadHex(rclsid.Data3, 4) & "-"
    
    Dim lData4Loop As Long
    For lData4Loop = 0 To 7
        If lData4Loop = 2 Then sHexCLSID = sHexCLSID & "-"
        sHexCLSID = sHexCLSID & PadHex(rclsid.Data4(lData4Loop), 2)
    
    Next lData4Loop
    
    VBA_CLSIDFromString = sHexCLSID & "}"
    Debug.Assert Len(VBA_CLSIDFromString) = 38
End Function

Private Function PadHex(ByVal lNum As Long, ByVal lDigits As Long) As String
    PadHex = Right(String(lDigits, "0") & Hex$(lNum), lDigits)
End Function

Public Function WMI_COMClassVersion(ByVal sClsId As String) As String
    Dim oWMIReg As Object
    Set oWMIReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
             ".rootdefault:StdRegProv")
    Dim sVersionString As String
    oWMIReg.GetStringValue &H80000002, "SOFTWAREClassesCLSID" & sClsId & "Version", "", sVersionString
    WMI_COMClassVersion = sVersionString

End Function


Public Function WhatVersionOfProgID(sClass As String) As String
    
    Dim sClsId As String
    sClsId = VBA_CLSIDFromString(sClass)
    
    WhatVersionOfProgID = WMI_COMClassVersion(sClsId)
    Exit Function
End Function

Private Sub TestWhatVersionOfProgID()
    Debug.Assert WhatVersionOfProgID("MSXML2.ServerXMLHTTP") = "3.0"
End Sub


Appendix A

Sweeping my registry for instances of MSXML2.ServerXMLHTTP turned up the following


Computer\HKEY_CLASSES_ROOT\CLSID\{88d96a0b-f192-11d4-a65f-0040963251e5}\ProgID
Computer\HKEY_CLASSES_ROOT\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\ProgID
Computer\HKEY_CLASSES_ROOT\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\VersionIndependentProgID
Computer\HKEY_CLASSES_ROOT\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\ProgID
Computer\HKEY_CLASSES_ROOT\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\VersionIndependentProgID
Computer\HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\VersionIndependentProgID
Computer\HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{88d96a0b-f192-11d4-a65f-0040963251e5}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\VersionIndependentProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Msxml2.ServerXMLHTTP
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Msxml2.ServerXMLHTTP.3.0
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Msxml2.ServerXMLHTTP.5.0
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Msxml2.ServerXMLHTTP.6.0
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Msxml2.ServerXMLHTTP\CurVer
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\{88D969EB-F192-11D4-A65F-0040963251E5}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\{88d96a0b-f192-11d4-a65f-0040963251e5}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\VersionIndependentProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\VersionIndependentProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\CLSID\{88D969EB-F192-11D4-A65F-0040963251E5}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\CLSID\{88d96a0b-f192-11d4-a65f-0040963251e5}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\CLSID\{AFB40FFD-B609-40A3-9828-F88BBE11E4E3}\VersionIndependentProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\ProgID
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\CLSID\{AFBA6B42-5692-48EA-8141-DC517DCF0EF1}\VersionIndependentProgID


Links

No comments:

Post a Comment