Comment mettre à jour par programmation les références OCX dans les projets vb6?

StackOverflow https://stackoverflow.com/questions/620535

  •  05-07-2019
  •  | 
  •  

Question

Je casse périodiquement la compatibilité binaire et je dois recompiler une application vb6 complète composée de plusieurs dizaines de DLL ActiveX et OCX au total. J'ai écrit un script pour automatiser ce processus, mais j'ai rencontré un problème.

Lorsqu'un OCX est recompilé avec la compatibilité de projet, sa version est incrémentée et les projets référençant l'OCX ne seront pas recompilés tant que leur référence ne sera pas mise à jour vers la nouvelle version. Ceci est vérifié automatiquement lorsque le projet est ouvert normalement et l'utilisateur est invité à mettre à jour la référence, mais je dois le faire dans un script.

Comment puis-je le faire?

Était-ce utile?

La solution

Je suppose que vous devez éditer les fichiers de projet (.vbp), les fichiers de formulaire (.frm) et les fichiers de contrôle (.ctl) qui référencent les DLL et les OCX et incrémentent le numéro de version de Typelib.

Vous trouverez le dernier numéro de version de la bibliothèque de types pour le contrôle / DLL dans le registre.

Cela peut être difficile en fonction du nombre de fichiers que vous avez.

Un hack consisterait à ouvrir le projet principal avec VB6 à l'aide de votre script et à envoyer les clés pour confirmer les références de mise à jour, puis enregistrer le projet.

Bonne chance

Autres conseils

Mon projet, géré pendant une décennie, consiste en une hiérarchie de deux douzaines de DLL ActiveX et d'une demi-douzaine de contrôles. Compilé avec un système de script également.

Je ne recommande pas de faire ce que vous faites.

Ce que nous faisons est le suivant

  1. Effectuer nos modifications, y compris les ajouts et tester dans l'EDI.
  2. Nous compilons à partir du bas de la hiérarchie vers le haut
  3. nous copions les fichiers récemment complétés dans un répertoire de révision par exemple 601, puis 602, etc., etc.
  4. nous créons le setup.exe
  5. lorsque la configuration est finalisée, nous copions sur le répertoire de révision dans notre directeur de compatibilité. Notez que nous ne pointez jamais vers le binaire compilé dans le répertoire du projet. Toujours à un répertoire de compatibilité qui a tout les DLL.

La raison pour laquelle cela fonctionne est que si vous examinez la source IDL à l'aide de l'outil Vue OLE, vous constaterez que tout contrôle référencé ou dll est ajouté à l'interface via un #include. Si vous pointez sur le fichier binaire de votre répertoire de projet, l'inclusion est extraite du registre, ce qui peut entraîner beaucoup d'étrangeté et de compatibilité.

Toutefois, si la DLL référencée est présente dans le répertoire qui contient le fichier binaire et est utilisée pour la compatibilité binaire, VB6 l'utilisera à la place de ce que le registre contient.

Maintenant, il y a un problème que vous rencontrez peu fréquemment. Considérez cette hiérarchie

  • MyUtilityDLL
  • MyObjectDLL
  • MyUIDLL
  • MyEXE

Si vous AJOUTEZ une propriété ou une méthode à une classe dans MyUtilityDLL, il se peut que MyUIDLL ne compile pas, ce qui donne une erreur d'incompatibilité binaire si vous êtes chanceux ou une erreur étrange telle que [inref]. Dans tous les cas, la solution consiste à compiler MyUtilityDLL, puis à copier immédiatement MyUtilityDLL dans le répertoire de compatibilité. Ensuite, le reste de la compilation automatisée fonctionnera correctement.

Vous pouvez inclure cette étape dans la construction automatisée.

Notez que dans de nombreux cas, les projets fonctionneront bien dans l'EDI. Si vous en êtes maintenant conscient, vous risquez de vous arracher les cheveux.

Nous procédons de la même manière, c’est-à-dire que nous manipulons les références aux OCX utilisés directement dans les fichiers VB6 .vbp, dans notre Outil de mise à jour des références de projet VB6 ( à télécharger ici ) . Généralement, il est utilisé pour mettre à jour les références lorsque l’ActiveX utilisé change de numéro de version, de CLSID, etc.

 entrer la description de l'image ici

Les outils sont open-source afin que toutes les personnes intéressées par ce problème puissent emprunter nos extraits de code VB pour mettre en œuvre des tâches comme celles-ci.

Notre outil est écrit en Visual Basic 6 et utilise tlbinf32.dll (la DLL d'informations de bibliothèque de types) qui vous permet d'extraire par programme des informations à partir de bibliothèques de types.

Auto-réponse: j'ai écrit du code vb6 pour effectuer la mise à niveau par programme. Il n’a pas fait l’objet de tests approfondis. Il existe probablement quelques bugs ici et là dans certains cas, mais j’ai utilisé avec succès.

Option Explicit

Const HKEY_LOCAL_MACHINE As Long = &H80000002
Const KEY_ENUMERATE_SUB_KEYS As Long = 8
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, lpReserved As Long, ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long

'''Returns the expected major version of a GUID if it exists, and otherwise returns the highest registered major version.
Public Function GetOcxMajorVersion(ByVal guid As String, Optional ByVal expected_version As Long) As Long
    Const BUFFER_SIZE As Long = 255
    Dim reg_key As Long
    Dim ret As Long
    Dim enum_index As Long
    Dim max_version As Long: max_version = -1

    ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\Classes\TypeLib\{" & guid & "}", 0, KEY_ENUMERATE_SUB_KEYS, reg_key)
    If ret <> 0 Then Err.Raise ret, , "Failed to open registry key."
    Do
        'Store next subkey name in buffer
        Dim buffer As String: buffer = Space(BUFFER_SIZE)
        Dim cur_buffer_size As Long: cur_buffer_size = BUFFER_SIZE
        ret = RegEnumKeyEx(reg_key, enum_index, buffer, cur_buffer_size, ByVal 0&, vbNullString, ByVal 0&, ByVal 0&)
        If ret <> 0 Then Exit Do
        buffer = Left(buffer, cur_buffer_size)

        'Keep most likely version
        buffer = Split(buffer, ".")(0)
        If Not buffer Like "*[!0-9A-B]*" And Len(buffer) < 4 Then
            Dim v As Long: v = CLng("&H" & buffer) 'convert from hex
            If v = expected_version Then
                max_version = v
                Exit Do
            ElseIf max_version < v Then
                max_version = v
            End If
        End If

        enum_index = enum_index + 1
    Loop
    RegCloseKey reg_key

    If max_version = -1 Then Err.Raise -1, , "Failed to enumerate any viable subkeys."
    GetOcxMajorVersion = max_version
End Function

Public Function RemoveFilename(ByVal path As String) As String
    Dim folders() As String: folders = Split(Replace(path, "/", "\"), "\")
    RemoveFilename = Left(path, Len(path) - Len(folders(UBound(folders))))
End Function

'''Changes any invalid OCX references to newer registered version
Public Sub UpdateFileOCXReferences(ByVal path As String)
    Dim file_data As String
    Dim changes_made As Boolean

    'Read
    Dim fn As Long: fn = FreeFile
    Open path For Input As fn
        While Not EOF(fn)
            Dim line As String
            Line Input #fn, line

            'check for ocx reference line
            If LCase(line) Like "object*=*{*-*-*-*-*}[#]*#.#*[#]#*;*.ocx*" Then
                'get guid
                Dim guid_start As Long: guid_start = InStr(line, "{") + 1
                Dim guid_end As Long: guid_end = InStr(line, "}")
                Dim guid As String: guid = Mid(line, guid_start, guid_end - guid_start)

                'get reference major version
                Dim version_start As Long: version_start = InStr(line, "#") + 1
                Dim version_end As Long: version_end = InStr(version_start + 1, line, ".")
                Dim version_text As String: version_text = Mid(line, version_start, version_end - version_start)

                'play it safe
                If Len(guid) <> 32 + 4 Then Err.Raise -1, , "GUID has unexpected length."
                If Len(version_text) > 4 Then Err.Raise -1, , "Major version is larger than expected."
                If guid Like "*[!0-9A-F-]*" Then Err.Raise -1, , "GUID has unexpected characters."
                If version_text Like "*[!0-9]*" Then Err.Raise -1, , "Major version isn't an integer."

                'get registry major version
                Dim ref_version As Long: ref_version = CLng(version_text)
                Dim reg_version As Long: reg_version = GetOcxMajorVersion(guid, ref_version)

                'change line if necessary
                If reg_version < ref_version Then
                    Err.Raise -1, , "Registered version precedes referenced version."
                ElseIf reg_version > ref_version Then
                    line = Left(line, version_start - 1) & CStr(reg_version) & Mid(line, version_end)
                    changes_made = True
                End If
            End If

            file_data = file_data & line & vbNewLine
        Wend
    Close fn

    'Write
    If changes_made Then
        Kill path
        Open path For Binary As fn
            Put fn, , file_data
        Close fn
    End If
End Sub

'''Changes any invalid in included files to newer registered version
Public Sub UpdateSubFileOCXReferences(ByVal path As String)
    Dim folder As String: folder = RemoveFilename(path)
    Dim fn As Long: fn = FreeFile
    Open path For Input As fn
        While Not EOF(fn)
            Dim line As String
            Line Input #fn, line

            If LCase(line) Like "form=*.frm" _
                            Or LCase(line) Like "usercontrol=*.ctl" Then
                Dim file As String: file = folder & Mid(line, InStr(line, "=") + 1)
                If Dir(file) <> "" Then
                    UpdateFileOCXReferences file
                End If
            End If
        Wend
    Close fn
End Sub
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top