VB6 프로젝트에서 OCX 참조를 프로그래밍 방식으로 업데이트하려면 어떻게해야합니까?

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

  •  05-07-2019
  •  | 
  •  

문제

주기적으로 이진 호환성을 깨고 총 수십 개의 ActiveX DLL 및 OCX로 구성된 전체 VB6 응용 프로그램을 다시 컴파일해야합니다. 이 프로세스를 자동화하기 위해 스크립트를 작성했지만 문제가 발생했습니다.

OCX가 프로젝트 호환성으로 재 컴파일되면 버전이 증가하고 OCX를 참조하는 프로젝트는 참조가 새 버전으로 업데이트 될 때까지 다시 컴파일하지 않습니다. 프로젝트가 정상적으로 열리면 자동으로 확인되며 사용자가 참조를 업데이트하라는 메시지가 표시되지만 스크립트로 수행해야합니다.

어떻게해야하나요?

도움이 되었습니까?

해결책

DLL 및 OCXS를 참조하고 TypLib 버전 번호를 증분하는 프로젝트 파일 (.vbp), 양식 파일 (.FRM) 및 제어 파일 (.CTL)을 편집해야한다고 생각합니다.

레지스트리에서 Control / DLL의 최신 TypLib 버전 번호를 찾을 수 있습니다.

이것은 당신이 가지고있는 파일의 수에 따라 고통 일 수 있습니다.

해킹은 스크립트를 사용하여 VB6을 사용하여 기본 프로젝트를 열고 키를 보내서 업데이트 참조를 확인한 다음 프로젝트를 저장하는 것입니다.

행운을 빕니다

다른 팁

10 년 동안 유지되는 나의 프로젝트는 24 개의 ActiveX DLL과 6 개의 컨트롤의 계층으로 구성됩니다. 스크립트 시스템도 컴파일했습니다.

나는 당신이하고있는 일을 권장하지 않습니다.

우리가하는 일은 다음과 같습니다

  1. IDE에서 추가 및 테스트를 포함하여 변경 사항을 변경하십시오.
  2. 우리는 계층 구조의 맨 아래에서 상단으로 컴파일합니다.
  3. 새로 준수 한 파일을 예를 들어 601, 602 등과 같은 개정 디렉토리에 복사합니다.
  4. 우리는 setup.exe를 만듭니다
  5. 설정이 완료되면 개정 디렉토리를 통해 호환 디렉터로 복사합니다. 참고 프로젝트 디렉토리에서 컴파일 된 바이너리를 가리키지 않습니다. 항상 모든 DLL이있는 컴퓨팅 디렉토리로.

이것이 작동하는 이유는 Ole View 도구를 사용하여 IDL 소스를 보면 #include를 통해 참조 된 컨트롤 또는 DLL이 인터페이스에 추가되기 때문입니다. 프로젝트 디렉토리의 바이너리를 가리키면 포함 내용이 레지스트리에서 픽업되어 많은 경계와 호환성을 초래할 수 있습니다.

그러나 참조 된 DLL이 이진 호환성에 사용되는 동안 이진이 존재하는 디렉토리에 존재하는 경우 VB6은 레지스트리의 모든 대신이를 사용합니다.

이제 당신이 드물게 얻을 문제가 있습니다. 이 상속장을 고려하십시오

  • myutilitydll
  • myobjectdll
  • myuidll
  • MyExe

MyUtilityDll의 클래스에 속성이나 방법을 추가하면 MyUidll이 운이 좋거나 [inref]와 같은 이상한 오류 인 경우 이진 비 호환 오류를 제공 할 수 없습니다. 어쨌든 솔루션은 myUtilityDll을 컴파일 한 다음 즉시 myUtilityDll을 호환 디렉토리에 복사하는 것입니다. 그러면 나머지 자동화 된 컴파일은 제대로 작동합니다.

이 단계를 자동화 된 빌드에 포함시킬 수 있습니다.

많은 경우에 프로젝트는 IDE에서 잘 작동합니다. 당신이 지금 이것을 알고 있다면 당신은 당신의 머리카락을 꺼낼 수 있습니다.

우리는 비슷한 일을하고 있습니다. 즉 VB6 프로젝트 참조 업데이트 도구 (여기에서 다운로드하십시오). 일반적으로 사용 된 ActiveX가 버전 번호, CLSID 등을 변경할 때 참조를 업데이트하는 데 사용됩니다.

enter image description here

이 도구는 오픈 소스 이므로이 문제에 관심이있는 모든 사람은 VB 코드 스 니펫을 빌려서 이와 같은 작업을 구현할 수 있습니다.

당사의 도구는 Visual Basic 6로 작성되었으며 Tlbinf32.dll (Typelib Information DLL)을 사용하여 라이브러리 유형에서 정보를 프로그래밍 방식으로 추출 할 수 있습니다.

Selfanswer : 프로그래밍 방식으로 업그레이드를 수행하기 위해 VB6 코드를 작성했습니다. 그것은 광범위하게 테스트되지 않았으며, 코너 케이스에는 몇 가지 버그가있을 수 있지만 성공적으로 사용했습니다.

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top