Come posso aggiornare a livello di codice i riferimenti OCX nei progetti vb6?

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

  •  05-07-2019
  •  | 
  •  

Domanda

Rompo periodicamente la compatibilità binaria e devo ricompilare un'intera applicazione vb6 composta da diverse dozzine di DLL ActiveX e OCX in totale. Ho scritto uno script per automatizzare questo processo, ma ho riscontrato un problema.

Quando un OCX viene ricompilato con la compatibilità del progetto, la sua versione viene incrementata e i progetti che fanno riferimento a OCX non si ricompilano fino a quando il loro riferimento non viene aggiornato alla nuova versione. Questo viene controllato automaticamente quando il progetto viene aperto normalmente e all'utente viene richiesto di aggiornare il riferimento, ma devo farlo in uno script.

Come posso farlo?

È stato utile?

Soluzione

Suppongo che dovresti modificare i file di progetto (.vbp), i file di modulo (.frm) e i file di controllo (.ctl) che fanno riferimento a DLL e OCX e aumentano il numero di versione del typelib.

Troverai l'ultimo numero di versione di typelib per il controllo / DLL nel registro.

Questo potrebbe essere un problema a seconda di quanti file hai.

Un trucco sarebbe aprire il progetto principale con VB6 usando lo script e inviare le chiavi per confermare i riferimenti di aggiornamento e quindi salvare il progetto.

Buona fortuna

Altri suggerimenti

Il mio progetto, mantenuto per oltre un decennio, consiste in una gerarchia di due dozzine di DLL ActiveX e una mezza dozzina di controlli. Compilato anche con un sistema di script.

Non consiglio di fare quello che stai facendo.

Quello che facciamo è il seguente

  1. Apporta le nostre modifiche incluse le aggiunte e test nell'IDE.
  2. Compiliamo dalla parte inferiore del file gerarchia verso l'alto
  3. copiamo i file appena rispettati una directory di revisione per esempio 601, quindi 602 ecc ecc.
  4. creiamo setup.exe
  5. quando l'installazione è finalizzata, copiamo sopra la directory di revisione nel nostro direttore di compatibilità. Nota noi non indicare mai il binario compilato nella directory del progetto. Sempre a una directory di compatibilità che ha tutto le DLL.

Il motivo per cui funziona è che se guardi l'origine IDL usando lo strumento OLE View scoprirai che qualsiasi controllo o dll referenziato viene aggiunto all'interfaccia tramite un #include. Se indichi il binario nella directory del tuo progetto, l'inclusione viene prelevata dal registro, il che può portare a molta stranezza e compatibilità.

Tuttavia, se la directory di riferimento è presente nella directory in cui esiste il file binario mentre viene utilizzato per la compatibilità binaria, VB6 lo utilizzerà invece di qualsiasi cosa nel registro.

Ora c'è un problema che potresti riscontrare di rado. Considera questa erirarchia

  • MyUtilityDLL
  • MyObjectDLL
  • MyUIDLL
  • MyEXE

Se AGGIUNGI una proprietà o un metodo a una classe in MyUtilityDLL MyUIDLL potrebbe non essere compilato dando un errore di incompatibilità binario se sei fortunato o uno strano errore come [inref]. In ogni caso, la soluzione è compilare MyUtilityDLL e quindi copiare immediatamente MyUtilityDLL nella directory di compatibilità. Quindi il resto della compilazione automatizzata funzionerà correttamente.

Potresti voler includere questo passaggio nella build automatizzata.

Nota che in molti casi i progetti funzioneranno bene nell'IDE. Se ora ne sei consapevole, potresti strapparti i capelli.

Stiamo facendo cose simili, cioè manipolando i riferimenti agli OCX usati direttamente nei file .vbp VB6, nei nostri Strumento di aggiornamento dei riferimenti al progetto VB6 ( scarica qui ) . Generalmente viene utilizzato per aggiornare i riferimenti quando gli ActiveX utilizzati cambiano i loro numeri di versione, CLSID, ecc.

 inserisci qui la descrizione dell'immagine

Gli strumenti sono open-source, quindi chiunque sia interessato a questo problema può prendere in prestito i nostri frammenti di codice VB per implementare attività come queste.

Il nostro strumento è scritto in Visual Basic 6 e utilizza tlbinf32.dll (la DLL delle informazioni di TypeLib) che consente di estrarre a livello di programmazione informazioni dalle librerie dei tipi.

Risposta automatica: ho scritto del codice vb6 per eseguire l'aggiornamento a livello di codice. Non è ampiamente testato, ci sono probabilmente alcuni bug qua e là per casi angolari, ma l'ho usato con successo.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top