Lấy dữ liệu Foxpro

Liên hệ QC
:) vấn đề chính là nằm ở việc gọi EXE từ chương trình chính (Excel) để thực thi mà không phải là gọi trực tiếp từ DLL. Còn việc file EXE lại gọi hàm xử lý từ file DLL khác nó càng đi đường vòng nữa chứ không cải thiện tốc độ gì cả. Đối với ví dụ trên là kết nối với Foxpro database thì nó code đơn giản, nên tôi viết trực tiếp trong EXE luôn chứ không cần phải qua một DLL cho nó rườm rà.

View attachment 272452
thì tùy thôi tại thấy keo EXE nó chạy chậm hơn nên tôi mới vẻ ra vậy
Nhưng có 1 thực tế là nếu viết code nhiều thật nhiều vào ActiveX EXE thì trình code phải đạt theo tiêu chí X ... nếu không nó báo vài chục em Virus là thường ... nếu cũng Files đó chuyển qua ActiveX DLL thì lại ko có em nào cả

Cơ bản khác nhau vài dòng trên thôi ... còn tùy mình thích kiểu gì ??!!!

Tôi viết thêm vào cho nó lấy qua Internet luôn cho máu chút ... như nói bài trước
xong cái này nghiên cứu viết thêm cái Co và giản ============== là xong thôi -0-0-0-

Liên kết: https://youtu.be/MTOBzP72hOI
 
Lần chỉnh sửa cuối:
Chia sẻ thư viện BSDataService32 để kết nối database 32-bit trong ứng dụng 64-bit
(Hướng dẫn trong video này lấy ví dụ CSDL Foxpro tại bài đầu tiên)
Thư viện BSDataService32 là miễn phí, hỗ trợ cho những người chỉ dùng hàm và công cụ mà không biết lập trình (làm theo các bước trong video dưới đây) ; với người lập trình cũng có thể viết code để tùy biến lấy dữ liệu.
(*) Download thư viện BSDataService32
(*) Video hướng dẫn chi tiết ứng dụng
 
Chia sẻ thư viện BSDataService32 để kết nối database 32-bit trong ứng dụng 64-bit
(Hướng dẫn trong video này lấy ví dụ CSDL Foxpro tại bài đầu tiên)
Thư viện BSDataService32 là miễn phí, hỗ trợ cho những người chỉ dùng hàm và công cụ mà không biết lập trình (làm theo các bước trong video dưới đây) ; với người lập trình cũng có thể viết code để tùy biến lấy dữ liệu.
(*) Download thư viện BSDataService32
(*) Video hướng dẫn chi tiết ứng dụng
2 File viết = VB6 ... rảnh cũng bắt trước làm 1 cái dùng thôi :D
1.PNG2.PNG
 
2 File viết = VB6 ... rảnh cũng bắt trước làm 1 cái dùng thôi :D
View attachment 272477View attachment 272478

Trong tình huống viết ứng dụng với dữ liệu 32-bit thì mình viết VB6 rất nhanh gọn. Vì chỉ làm với data 32-bit chứ không đụng chạm hệ thống khác nên yên tâm làm VB6. Dung lượng nhỏ tí teo. Cái file "setup.exe" để cài đặt thư viện cũng làm luôn trong VB6 cho người dùng tiện cài đặt và nhìn có vẻ chuyên nghiệp :).
 
Trong tình huống viết ứng dụng với dữ liệu 32-bit thì mình viết VB6 rất nhanh gọn. Vì chỉ làm với data 32-bit chứ không đụng chạm hệ thống khác nên yên tâm làm VB6. Dung lượng nhỏ tí teo. Cái file "setup.exe" để cài đặt thư viện cũng làm luôn trong VB6 cho người dùng tiện cài đặt và nhìn có vẻ chuyên nghiệp :).
Thử nghĩ cách load cái vfpoledb.dll Từ trong tài nguyên VB6 xem có được không ... thay vì dùng File Setup xả nén nó vào system xong đăng ký no với Run As khi chạy file setup
 
Cách cài đặt thư viện "vfpoledb.dll" trong VB6

Khai báo hàm API:
Tôi dùng unicode nên code sẽ dài hơn chút nhưng sẽ an toàn nếu đường dẫn file DLL chứa ký tự có dấu.
C#:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteW" (ByVal hwnd As Long, _
                                                                               ByVal lpOperation As String, _
                                                                               ByVal lpFile As String, _
                                                                               ByVal lpParameters As String, _
                                                                               ByVal lpDirectory As String, _
                                                                               ByVal nShowCmd As Long) As Long

Lệnh chạy install:

C#:
Private Sub InstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
   'Đường dẫn DLL tùy bạn chọn. Nếu lấy từ chính file exe đang chạy thì là:  App.Path & "\vfpoledb.dll"
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll"" /s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Install successful." & vbNewLine & _
               "Application can use classes in this library.", vbInformation
        Unload Me
    End If
End Sub
'-------------------------------------------------------------------------------------
Private Sub UninstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll""  /u/s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Uninstall successful." & vbNewLine & _
               "Application can not use classes in this library.", vbInformation
        Unload Me
    End If
End Sub

Mã nguồn trên là VB6 nhưng dùng mẫu định dạng C# của GPE cho đẹp. Các bạn không nhầm lẫn loại code nhé.
 
Lần chỉnh sửa cuối:
vẫn phải đăng ký nó với windows ... ít ngày nữa rảnh mạnh thử cách ko cần đăng ký xem có dc ko ... dùng hàm load nó
 
Tôi thấy có cái hàm của người Nga viết bằng VB6 để làm việc với thư viện COM mà không cần đăng ký (register). Tôi không rành mấy vụ này nên post lên đây xem có giúp được gì không.
- module load thư viện COM.
- cái tool đọc thông tin thư viện - Library Info

Screen Shot 2022-02-26 at 08.22.54.png


Mã:
' The module modTrickUnregCOM.bas - for working with COM libraries without registration.
' © Krivous Anatolii Anatolevich (The trick), 2015

Option Explicit

Public 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 lpszCLSID As Long, _
                         ByRef clsid As GUID) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef src As Any, _
                         ByRef dst As Any) As Long
Private Declare Function SysFreeString Lib "oleaut32" ( _
                         ByVal lpbstr As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" _
                         Alias "LoadLibraryW" ( _
                         ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
                         ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
                         ByVal hModule As Long, _
                         ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" ( _
                         ByVal pvInstance As Any, _
                         ByVal oVft As Long, _
                         ByVal cc As Integer, _
                         ByVal vtReturn As Integer, _
                         ByVal cActuals As Long, _
                         ByRef prgvt As Any, _
                         ByRef prgpvarg As Any, _
                         ByRef pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" ( _
                         ByVal szFile As Long, _
                         ByVal regkind As Long, _
                         ByRef pptlib As IUnknown) As Long
Private Declare Function memcpy Lib "kernel32" _
                         Alias "RtlMoveMemory" ( _
                         ByRef Destination As Any, _
                         ByRef Source As Any, _
                         ByVal Length As Long) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
                         ByVal punkOuter As IUnknown, _
                         ByVal pvThis As IUnknown, _
                         ByVal ptinfo As IUnknown, _
                         ByRef ppunkStdDisp As IUnknown) As Long
                        
Private Const IID_IClassFactory   As String = "{00000001-0000-0000-C000-000000000046}"
Private Const IID_IUnknown        As String = "{00000000-0000-0000-C000-000000000046}"
Private Const CC_STDCALL          As Long = 4
Private Const REGKIND_NONE        As Long = 2
Private Const TKIND_COCLASS       As Long = 5
Private Const TKIND_DISPATCH      As Long = 4
Private Const TKIND_INTERFACE     As Long = 3

Dim iidClsFctr      As GUID
Dim iidUnk          As GUID
Dim isInit          As Boolean

' // Get all co-classes described in type library.
Public Function GetAllCoclasses( _
                ByRef path As String, _
                ByRef listOfClsid() As GUID, _
                ByRef listOfNames() As String, _
                ByRef countCoClass As Long) As Boolean
                
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim count   As Long
    Dim index   As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    
    ret = LoadTypeLibEx(StrPtr(path), REGKIND_NONE, typeLib)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    count = ITypeLib_GetTypeInfoCount(typeLib)
    countCoClass = 0
    
    If count > 0 Then
    
        ReDim listOfClsid(count - 1)
        ReDim listOfNames(count - 1)
        
        For index = 0 To count - 1
        
            ret = ITypeLib_GetTypeInfo(typeLib, index, typeInf)
                        
            If ret Then
                Err.Raise ret
                Exit Function
            End If
            
            ITypeInfo_GetTypeAttr typeInf, pAttr
            
            GetMem4 ByVal pAttr + &H28, tKind
            
            If tKind = TKIND_COCLASS Then
            
                memcpy listOfClsid(countCoClass), ByVal pAttr, Len(listOfClsid(countCoClass))
                ret = ITypeInfo_GetDocumentation(typeInf, -1, listOfNames(countCoClass), vbNullString, 0, vbNullString)
                
                If ret Then
                    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
                    Err.Raise ret
                    Exit Function
                End If
                
                countCoClass = countCoClass + 1
                
            End If
            
            ITypeInfo_ReleaseTypeAttr typeInf, pAttr
            
            Set typeInf = Nothing
            
        Next
        
    End If
    
    If countCoClass Then
        
        ReDim Preserve listOfClsid(countCoClass - 1)
        ReDim Preserve listOfNames(countCoClass - 1)
    
    Else
    
        Erase listOfClsid()
        Erase listOfNames()
        
    End If
    
    GetAllCoclasses = True
    
End Function

' // Create IDispach implementation described in type library.
Public Function CreateIDispatch( _
                ByRef obj As IUnknown, _
                ByRef typeLibPath As String, _
                ByRef interfaceName As String) As Object
                
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim retObj  As IUnknown
    Dim pAttr   As Long
    Dim tKind   As Long
    
    ret = LoadTypeLibEx(StrPtr(typeLibPath), REGKIND_NONE, typeLib)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    ret = ITypeLib_FindName(typeLib, interfaceName, 0, typeInf, 0, 1)
    
    If typeInf Is Nothing Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
    
    ITypeInfo_GetTypeAttr typeInf, pAttr
    GetMem4 ByVal pAttr + &H28, tKind
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
    
    If tKind = TKIND_DISPATCH Then
        Set CreateIDispatch = obj
        Exit Function
    ElseIf tKind <> TKIND_INTERFACE Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ret = CreateStdDispatch(Nothing, obj, typeInf, retObj)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    Set CreateIDispatch = retObj

End Function

' // Create object by Name.
Public Function CreateObjectEx2( _
                ByRef pathToDll As String, _
                ByRef pathToTLB As String, _
                ByRef className As String) As IUnknown
                
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    Dim clsid   As GUID
    
    ret = LoadTypeLibEx(StrPtr(pathToTLB), REGKIND_NONE, typeLib)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    ret = ITypeLib_FindName(typeLib, className, 0, typeInf, 0, 1)
    
    If typeInf Is Nothing Then
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If

    ITypeInfo_GetTypeAttr typeInf, pAttr
    
    GetMem4 ByVal pAttr + &H28, tKind
    
    If tKind = TKIND_COCLASS Then
        memcpy clsid, ByVal pAttr, Len(clsid)
    Else
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If
    
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
            
    Set CreateObjectEx2 = CreateObjectEx(pathToDll, clsid)
    
End Function
                
' // Create object by CLSID and path.
Public Function CreateObjectEx( _
                ByRef path As String, _
                ByRef clsid As GUID) As IUnknown
                
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim isLoad  As Boolean
    
    hLib = GetModuleHandle(StrPtr(path))
    
    If hLib = 0 Then
    
        hLib = LoadLibrary(StrPtr(path))
        If hLib = 0 Then
            Err.Raise 53, , Error(53) & " " & Chr$(34) & path & Chr$(34)
            Exit Function
        End If
        
        isLoad = True
        
    End If
    
    lpAddr = GetProcAddress(hLib, "DllGetClassObject")
    
    If lpAddr = 0 Then
        If isLoad Then FreeLibrary hLib
        Err.Raise 453, , "Can't find dll entry point DllGetClasesObject in " & Chr$(34) & path & Chr$(34)
        Exit Function
    End If

    If Not isInit Then
        CLSIDFromString StrPtr(IID_IClassFactory), iidClsFctr
        CLSIDFromString StrPtr(IID_IUnknown), iidUnk
        isInit = True
    End If
    
    Dim ret     As Long
    Dim out     As IUnknown
    
    ret = DllGetClassObject(lpAddr, clsid, iidClsFctr, out)
    
    If ret = 0 Then

        ret = IClassFactory_CreateInstance(out, 0, iidUnk, CreateObjectEx)
    
    Else
    
        If isLoad Then FreeLibrary hLib
        Err.Raise ret
        Exit Function
        
    End If
    
    Set out = Nothing
    
    If ret Then
    
        If isLoad Then FreeLibrary hLib
        Err.Raise ret

    End If
    
End Function

' // Unload DLL if not used.
Public Function UnloadLibrary( _
                ByRef path As String) As Boolean
                
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim ret     As Long
    
    If Not isInit Then Exit Function
    
    hLib = GetModuleHandle(StrPtr(path))
    If hLib = 0 Then Exit Function
    
    lpAddr = GetProcAddress(hLib, "DllCanUnloadNow")
    If lpAddr = 0 Then Exit Function
    
    ret = DllCanUnloadNow(lpAddr)
    
    If ret = 0 Then
        FreeLibrary hLib
        UnloadLibrary = True
    End If
    
End Function

' // Call "DllGetClassObject" function using a pointer.
Private Function DllGetClassObject( _
                 ByVal funcAddr As Long, _
                 ByRef clsid As GUID, _
                 ByRef iid As GUID, _
                 ByRef out As IUnknown) As Long
                
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = VarPtr(clsid)
    params(1) = VarPtr(iid)
    params(2) = VarPtr(out)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
            
    If resultCall Then Err.Raise 5: Exit Function
    
    DllGetClassObject = pReturn
    
End Function

' // Call "DllCanUnloadNow" function using a pointer.
Private Function DllCanUnloadNow( _
                 ByVal funcAddr As Long) As Long
                
    Dim resultCall  As Long
    Dim pReturn     As Variant
    
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
            
    If resultCall Then Err.Raise 5: Exit Function
    
    DllCanUnloadNow = pReturn
    
End Function

' // Call "IClassFactory:CreateInstance" method.
Private Function IClassFactory_CreateInstance( _
                 ByVal obj As IUnknown, _
                 ByVal punkOuter As Long, _
                 ByRef riid As GUID, _
                 ByRef out As IUnknown) As Long
    
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = punkOuter
    params(1) = VarPtr(riid)
    params(2) = VarPtr(out)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    IClassFactory_CreateInstance = pReturn
    
End Function

' // Call "ITypeLib:GetTypeInfoCount" method.
Private Function ITypeLib_GetTypeInfoCount( _
                 ByVal obj As IUnknown) As Long
    
    Dim resultCall  As Long
    Dim pReturn     As Variant

    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeLib_GetTypeInfoCount = pReturn
    
End Function

' // Call "ITypeLib:GetTypeInfo" method.
Private Function ITypeLib_GetTypeInfo( _
                 ByVal obj As IUnknown, _
                 ByVal index As Long, _
                 ByRef ppTInfo As IUnknown) As Long
    
    Dim params(1)   As Variant
    Dim types(1)    As Integer
    Dim list(1)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = index
    params(1) = VarPtr(ppTInfo)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &H10, CC_STDCALL, vbLong, 2, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeLib_GetTypeInfo = pReturn
    
End Function

' // Call "ITypeLib:FindName" method.
Private Function ITypeLib_FindName( _
                 ByVal obj As IUnknown, _
                 ByRef szNameBuf As String, _
                 ByVal lHashVal As Long, _
                 ByRef ppTInfo As IUnknown, _
                 ByRef rgMemId As Long, _
                 ByRef pcFound As Integer) As Long
    
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = StrPtr(szNameBuf)
    params(1) = lHashVal
    params(2) = VarPtr(ppTInfo)
    params(3) = VarPtr(rgMemId)
    params(4) = VarPtr(pcFound)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &H2C, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeLib_FindName = pReturn
    
End Function

' // Call "ITypeInfo:GetTypeAttr" method.
Private Sub ITypeInfo_GetTypeAttr( _
            ByVal obj As IUnknown, _
            ByRef ppTypeAttr As Long)
    
    Dim resultCall  As Long
    Dim pReturn     As Variant
    
    pReturn = VarPtr(ppTypeAttr)
    
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(pReturn), 0)
          
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub

' // Call "ITypeInfo:GetDocumentation" method.
Private Function ITypeInfo_GetDocumentation( _
                 ByVal obj As IUnknown, _
                 ByVal memid As Long, _
                 ByRef pBstrName As String, _
                 ByRef pBstrDocString As String, _
                 ByRef pdwHelpContext As Long, _
                 ByRef pBstrHelpFile As String) As Long
    
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = memid
    params(1) = VarPtr(pBstrName)
    params(2) = VarPtr(pBstrDocString)
    params(3) = VarPtr(pdwHelpContext)
    params(4) = VarPtr(pBstrHelpFile)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &H30, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeInfo_GetDocumentation = pReturn
    
End Function

' // Call "ITypeInfo:ReleaseTypeAttr" method.
Private Sub ITypeInfo_ReleaseTypeAttr( _
            ByVal obj As IUnknown, _
            ByVal ppTypeAttr As Long)
    
    Dim resultCall  As Long
    
    resultCall = DispCallFunc(obj, &H4C, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(ppTypeAttr)), 0)
          
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub
 

File đính kèm

  • Library info 2.zip
    17.8 KB · Đọc: 4
  • modTrickUnregCOM.zip
    2.9 KB · Đọc: 5
  • tl_ole.zip
    316.7 KB · Đọc: 5
Tôi thấy có cái hàm của người Nga viết bằng VB6 để làm việc với thư viện COM mà không cần đăng ký (register). Tôi không rành mấy vụ này nên post lên đây xem có giúp được gì không.
- module load thư viện COM.
- cái tool đọc thông tin thư viện - Library Info

View attachment 272485


Mã:
' The module modTrickUnregCOM.bas - for working with COM libraries without registration.
' © Krivous Anatolii Anatolevich (The trick), 2015

Option Explicit

Public 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 lpszCLSID As Long, _
                         ByRef clsid As GUID) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef src As Any, _
                         ByRef dst As Any) As Long
Private Declare Function SysFreeString Lib "oleaut32" ( _
                         ByVal lpbstr As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" _
                         Alias "LoadLibraryW" ( _
                         ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
                         ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
                         ByVal hModule As Long, _
                         ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" ( _
                         ByVal pvInstance As Any, _
                         ByVal oVft As Long, _
                         ByVal cc As Integer, _
                         ByVal vtReturn As Integer, _
                         ByVal cActuals As Long, _
                         ByRef prgvt As Any, _
                         ByRef prgpvarg As Any, _
                         ByRef pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" ( _
                         ByVal szFile As Long, _
                         ByVal regkind As Long, _
                         ByRef pptlib As IUnknown) As Long
Private Declare Function memcpy Lib "kernel32" _
                         Alias "RtlMoveMemory" ( _
                         ByRef Destination As Any, _
                         ByRef Source As Any, _
                         ByVal Length As Long) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
                         ByVal punkOuter As IUnknown, _
                         ByVal pvThis As IUnknown, _
                         ByVal ptinfo As IUnknown, _
                         ByRef ppunkStdDisp As IUnknown) As Long
                       
Private Const IID_IClassFactory   As String = "{00000001-0000-0000-C000-000000000046}"
Private Const IID_IUnknown        As String = "{00000000-0000-0000-C000-000000000046}"
Private Const CC_STDCALL          As Long = 4
Private Const REGKIND_NONE        As Long = 2
Private Const TKIND_COCLASS       As Long = 5
Private Const TKIND_DISPATCH      As Long = 4
Private Const TKIND_INTERFACE     As Long = 3

Dim iidClsFctr      As GUID
Dim iidUnk          As GUID
Dim isInit          As Boolean

' // Get all co-classes described in type library.
Public Function GetAllCoclasses( _
                ByRef path As String, _
                ByRef listOfClsid() As GUID, _
                ByRef listOfNames() As String, _
                ByRef countCoClass As Long) As Boolean
               
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim count   As Long
    Dim index   As Long
    Dim pAttr   As Long
    Dim tKind   As Long
   
    ret = LoadTypeLibEx(StrPtr(path), REGKIND_NONE, typeLib)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    count = ITypeLib_GetTypeInfoCount(typeLib)
    countCoClass = 0
   
    If count > 0 Then
   
        ReDim listOfClsid(count - 1)
        ReDim listOfNames(count - 1)
       
        For index = 0 To count - 1
       
            ret = ITypeLib_GetTypeInfo(typeLib, index, typeInf)
                       
            If ret Then
                Err.Raise ret
                Exit Function
            End If
           
            ITypeInfo_GetTypeAttr typeInf, pAttr
           
            GetMem4 ByVal pAttr + &H28, tKind
           
            If tKind = TKIND_COCLASS Then
           
                memcpy listOfClsid(countCoClass), ByVal pAttr, Len(listOfClsid(countCoClass))
                ret = ITypeInfo_GetDocumentation(typeInf, -1, listOfNames(countCoClass), vbNullString, 0, vbNullString)
               
                If ret Then
                    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
                    Err.Raise ret
                    Exit Function
                End If
               
                countCoClass = countCoClass + 1
               
            End If
           
            ITypeInfo_ReleaseTypeAttr typeInf, pAttr
           
            Set typeInf = Nothing
           
        Next
       
    End If
   
    If countCoClass Then
       
        ReDim Preserve listOfClsid(countCoClass - 1)
        ReDim Preserve listOfNames(countCoClass - 1)
   
    Else
   
        Erase listOfClsid()
        Erase listOfNames()
       
    End If
   
    GetAllCoclasses = True
   
End Function

' // Create IDispach implementation described in type library.
Public Function CreateIDispatch( _
                ByRef obj As IUnknown, _
                ByRef typeLibPath As String, _
                ByRef interfaceName As String) As Object
               
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim retObj  As IUnknown
    Dim pAttr   As Long
    Dim tKind   As Long
   
    ret = LoadTypeLibEx(StrPtr(typeLibPath), REGKIND_NONE, typeLib)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    ret = ITypeLib_FindName(typeLib, interfaceName, 0, typeInf, 0, 1)
   
    If typeInf Is Nothing Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
   
    ITypeInfo_GetTypeAttr typeInf, pAttr
    GetMem4 ByVal pAttr + &H28, tKind
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
   
    If tKind = TKIND_DISPATCH Then
        Set CreateIDispatch = obj
        Exit Function
    ElseIf tKind <> TKIND_INTERFACE Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ret = CreateStdDispatch(Nothing, obj, typeInf, retObj)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    Set CreateIDispatch = retObj

End Function

' // Create object by Name.
Public Function CreateObjectEx2( _
                ByRef pathToDll As String, _
                ByRef pathToTLB As String, _
                ByRef className As String) As IUnknown
               
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    Dim clsid   As GUID
   
    ret = LoadTypeLibEx(StrPtr(pathToTLB), REGKIND_NONE, typeLib)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    ret = ITypeLib_FindName(typeLib, className, 0, typeInf, 0, 1)
   
    If typeInf Is Nothing Then
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If

    ITypeInfo_GetTypeAttr typeInf, pAttr
   
    GetMem4 ByVal pAttr + &H28, tKind
   
    If tKind = TKIND_COCLASS Then
        memcpy clsid, ByVal pAttr, Len(clsid)
    Else
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If
   
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
           
    Set CreateObjectEx2 = CreateObjectEx(pathToDll, clsid)
   
End Function
               
' // Create object by CLSID and path.
Public Function CreateObjectEx( _
                ByRef path As String, _
                ByRef clsid As GUID) As IUnknown
               
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim isLoad  As Boolean
   
    hLib = GetModuleHandle(StrPtr(path))
   
    If hLib = 0 Then
   
        hLib = LoadLibrary(StrPtr(path))
        If hLib = 0 Then
            Err.Raise 53, , Error(53) & " " & Chr$(34) & path & Chr$(34)
            Exit Function
        End If
       
        isLoad = True
       
    End If
   
    lpAddr = GetProcAddress(hLib, "DllGetClassObject")
   
    If lpAddr = 0 Then
        If isLoad Then FreeLibrary hLib
        Err.Raise 453, , "Can't find dll entry point DllGetClasesObject in " & Chr$(34) & path & Chr$(34)
        Exit Function
    End If

    If Not isInit Then
        CLSIDFromString StrPtr(IID_IClassFactory), iidClsFctr
        CLSIDFromString StrPtr(IID_IUnknown), iidUnk
        isInit = True
    End If
   
    Dim ret     As Long
    Dim out     As IUnknown
   
    ret = DllGetClassObject(lpAddr, clsid, iidClsFctr, out)
   
    If ret = 0 Then

        ret = IClassFactory_CreateInstance(out, 0, iidUnk, CreateObjectEx)
   
    Else
   
        If isLoad Then FreeLibrary hLib
        Err.Raise ret
        Exit Function
       
    End If
   
    Set out = Nothing
   
    If ret Then
   
        If isLoad Then FreeLibrary hLib
        Err.Raise ret

    End If
   
End Function

' // Unload DLL if not used.
Public Function UnloadLibrary( _
                ByRef path As String) As Boolean
               
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim ret     As Long
   
    If Not isInit Then Exit Function
   
    hLib = GetModuleHandle(StrPtr(path))
    If hLib = 0 Then Exit Function
   
    lpAddr = GetProcAddress(hLib, "DllCanUnloadNow")
    If lpAddr = 0 Then Exit Function
   
    ret = DllCanUnloadNow(lpAddr)
   
    If ret = 0 Then
        FreeLibrary hLib
        UnloadLibrary = True
    End If
   
End Function

' // Call "DllGetClassObject" function using a pointer.
Private Function DllGetClassObject( _
                 ByVal funcAddr As Long, _
                 ByRef clsid As GUID, _
                 ByRef iid As GUID, _
                 ByRef out As IUnknown) As Long
               
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = VarPtr(clsid)
    params(1) = VarPtr(iid)
    params(2) = VarPtr(out)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
           
    If resultCall Then Err.Raise 5: Exit Function
   
    DllGetClassObject = pReturn
   
End Function

' // Call "DllCanUnloadNow" function using a pointer.
Private Function DllCanUnloadNow( _
                 ByVal funcAddr As Long) As Long
               
    Dim resultCall  As Long
    Dim pReturn     As Variant
   
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
           
    If resultCall Then Err.Raise 5: Exit Function
   
    DllCanUnloadNow = pReturn
   
End Function

' // Call "IClassFactory:CreateInstance" method.
Private Function IClassFactory_CreateInstance( _
                 ByVal obj As IUnknown, _
                 ByVal punkOuter As Long, _
                 ByRef riid As GUID, _
                 ByRef out As IUnknown) As Long
   
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = punkOuter
    params(1) = VarPtr(riid)
    params(2) = VarPtr(out)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    IClassFactory_CreateInstance = pReturn
   
End Function

' // Call "ITypeLib:GetTypeInfoCount" method.
Private Function ITypeLib_GetTypeInfoCount( _
                 ByVal obj As IUnknown) As Long
   
    Dim resultCall  As Long
    Dim pReturn     As Variant

    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeLib_GetTypeInfoCount = pReturn
   
End Function

' // Call "ITypeLib:GetTypeInfo" method.
Private Function ITypeLib_GetTypeInfo( _
                 ByVal obj As IUnknown, _
                 ByVal index As Long, _
                 ByRef ppTInfo As IUnknown) As Long
   
    Dim params(1)   As Variant
    Dim types(1)    As Integer
    Dim list(1)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = index
    params(1) = VarPtr(ppTInfo)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &H10, CC_STDCALL, vbLong, 2, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeLib_GetTypeInfo = pReturn
   
End Function

' // Call "ITypeLib:FindName" method.
Private Function ITypeLib_FindName( _
                 ByVal obj As IUnknown, _
                 ByRef szNameBuf As String, _
                 ByVal lHashVal As Long, _
                 ByRef ppTInfo As IUnknown, _
                 ByRef rgMemId As Long, _
                 ByRef pcFound As Integer) As Long
   
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = StrPtr(szNameBuf)
    params(1) = lHashVal
    params(2) = VarPtr(ppTInfo)
    params(3) = VarPtr(rgMemId)
    params(4) = VarPtr(pcFound)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &H2C, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeLib_FindName = pReturn
   
End Function

' // Call "ITypeInfo:GetTypeAttr" method.
Private Sub ITypeInfo_GetTypeAttr( _
            ByVal obj As IUnknown, _
            ByRef ppTypeAttr As Long)
   
    Dim resultCall  As Long
    Dim pReturn     As Variant
   
    pReturn = VarPtr(ppTypeAttr)
   
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(pReturn), 0)
         
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub

' // Call "ITypeInfo:GetDocumentation" method.
Private Function ITypeInfo_GetDocumentation( _
                 ByVal obj As IUnknown, _
                 ByVal memid As Long, _
                 ByRef pBstrName As String, _
                 ByRef pBstrDocString As String, _
                 ByRef pdwHelpContext As Long, _
                 ByRef pBstrHelpFile As String) As Long
   
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = memid
    params(1) = VarPtr(pBstrName)
    params(2) = VarPtr(pBstrDocString)
    params(3) = VarPtr(pdwHelpContext)
    params(4) = VarPtr(pBstrHelpFile)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &H30, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeInfo_GetDocumentation = pReturn
   
End Function

' // Call "ITypeInfo:ReleaseTypeAttr" method.
Private Sub ITypeInfo_ReleaseTypeAttr( _
            ByVal obj As IUnknown, _
            ByVal ppTypeAttr As Long)
   
    Dim resultCall  As Long
   
    resultCall = DispCallFunc(obj, &H4C, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(ppTypeAttr)), 0)
         
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub
Em nhìn là thấy chống mặt rồi
 
Tôi viết hàm sau để check 1 COM sử dụng chung cho VBA và VB6... chia sẻ cho ai cần nó
tối qua tới nay tôi thử với File vfpoledb.dll thì ko thành công ... vì cái gì đó thì tôi ko có biết
xem trong Registry thì ... khó nói lắm

Hàm sau trả về True nếu cái ActiveX COM đó đã đăng ký với Windows cấu trúc như sau
1/ VisualFoxProSQL = tên DLL
2/ FoxPro = tên Class
3/ Hoàn chỉnh là: Debug.Print CheckRegActiveX("VisualFoxProSQL.FoxPro")

Mã:
Function CheckRegActiveX(ByVal ProgID As String) As Boolean
    Rem Su dung Debug.Print CheckRegActiveX("VBLibraryLoad.cCOM")
    Rem Ham tra ve: True = Da dang Ky ; False = Chua Dang Ky
    Rem Ap dung cho ActiveX EXE va DLL
    Rem Debug.Print CheckRegActiveX("VBLibraryLoad.cCOM")
    On Error GoTo NextErr
    Debug.Assert Not CreateObject(ProgID) Is Nothing
NextErr:
    Rem If Err Then MsgBox Err.Description Else CheckRegActiveX = True
    If Err Then CheckRegActiveX = False Else CheckRegActiveX = True
End Function

Sub Main()
Debug.Print CheckRegActiveX("vfpoledb.ConnectionPage")
''Debug.Print CheckRegActiveX("VisualFoxProSQL.FoxPro")
End Sub

Mục đích hàm trên kiểm tra 1 cái COM DLL nào đó đã đăng ký hay chưa ... nếu chưa thì tùy ai đó xử lý bước tiếp theo vvv....

Tôi mới thử cho Python cũng ok luôn

Mã:
Debug.Print CheckRegActiveX("PythonImportDBF2Excel.Application")
 
Lần chỉnh sửa cuối:
Tôi thấy có cái hàm của người Nga viết bằng VB6 để làm việc với thư viện COM mà không cần đăng ký (register). Tôi không rành mấy vụ này nên post lên đây xem có giúp được gì không.
- module load thư viện COM.
- cái tool đọc thông tin thư viện - Library Info

View attachment 272485


Mã:
' The module modTrickUnregCOM.bas - for working with COM libraries without registration.
' © Krivous Anatolii Anatolevich (The trick), 2015

Option Explicit

Public 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 lpszCLSID As Long, _
                         ByRef clsid As GUID) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef src As Any, _
                         ByRef dst As Any) As Long
Private Declare Function SysFreeString Lib "oleaut32" ( _
                         ByVal lpbstr As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" _
                         Alias "LoadLibraryW" ( _
                         ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
                         ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
                         ByVal hModule As Long, _
                         ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" ( _
                         ByVal pvInstance As Any, _
                         ByVal oVft As Long, _
                         ByVal cc As Integer, _
                         ByVal vtReturn As Integer, _
                         ByVal cActuals As Long, _
                         ByRef prgvt As Any, _
                         ByRef prgpvarg As Any, _
                         ByRef pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" ( _
                         ByVal szFile As Long, _
                         ByVal regkind As Long, _
                         ByRef pptlib As IUnknown) As Long
Private Declare Function memcpy Lib "kernel32" _
                         Alias "RtlMoveMemory" ( _
                         ByRef Destination As Any, _
                         ByRef Source As Any, _
                         ByVal Length As Long) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
                         ByVal punkOuter As IUnknown, _
                         ByVal pvThis As IUnknown, _
                         ByVal ptinfo As IUnknown, _
                         ByRef ppunkStdDisp As IUnknown) As Long
                     
Private Const IID_IClassFactory   As String = "{00000001-0000-0000-C000-000000000046}"
Private Const IID_IUnknown        As String = "{00000000-0000-0000-C000-000000000046}"
Private Const CC_STDCALL          As Long = 4
Private Const REGKIND_NONE        As Long = 2
Private Const TKIND_COCLASS       As Long = 5
Private Const TKIND_DISPATCH      As Long = 4
Private Const TKIND_INTERFACE     As Long = 3

Dim iidClsFctr      As GUID
Dim iidUnk          As GUID
Dim isInit          As Boolean

' // Get all co-classes described in type library.
Public Function GetAllCoclasses( _
                ByRef path As String, _
                ByRef listOfClsid() As GUID, _
                ByRef listOfNames() As String, _
                ByRef countCoClass As Long) As Boolean
             
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim count   As Long
    Dim index   As Long
    Dim pAttr   As Long
    Dim tKind   As Long
 
    ret = LoadTypeLibEx(StrPtr(path), REGKIND_NONE, typeLib)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    count = ITypeLib_GetTypeInfoCount(typeLib)
    countCoClass = 0
 
    If count > 0 Then
 
        ReDim listOfClsid(count - 1)
        ReDim listOfNames(count - 1)
     
        For index = 0 To count - 1
     
            ret = ITypeLib_GetTypeInfo(typeLib, index, typeInf)
                     
            If ret Then
                Err.Raise ret
                Exit Function
            End If
         
            ITypeInfo_GetTypeAttr typeInf, pAttr
         
            GetMem4 ByVal pAttr + &H28, tKind
         
            If tKind = TKIND_COCLASS Then
         
                memcpy listOfClsid(countCoClass), ByVal pAttr, Len(listOfClsid(countCoClass))
                ret = ITypeInfo_GetDocumentation(typeInf, -1, listOfNames(countCoClass), vbNullString, 0, vbNullString)
             
                If ret Then
                    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
                    Err.Raise ret
                    Exit Function
                End If
             
                countCoClass = countCoClass + 1
             
            End If
         
            ITypeInfo_ReleaseTypeAttr typeInf, pAttr
         
            Set typeInf = Nothing
         
        Next
     
    End If
 
    If countCoClass Then
     
        ReDim Preserve listOfClsid(countCoClass - 1)
        ReDim Preserve listOfNames(countCoClass - 1)
 
    Else
 
        Erase listOfClsid()
        Erase listOfNames()
     
    End If
 
    GetAllCoclasses = True
 
End Function

' // Create IDispach implementation described in type library.
Public Function CreateIDispatch( _
                ByRef obj As IUnknown, _
                ByRef typeLibPath As String, _
                ByRef interfaceName As String) As Object
             
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim retObj  As IUnknown
    Dim pAttr   As Long
    Dim tKind   As Long
 
    ret = LoadTypeLibEx(StrPtr(typeLibPath), REGKIND_NONE, typeLib)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    ret = ITypeLib_FindName(typeLib, interfaceName, 0, typeInf, 0, 1)
 
    If typeInf Is Nothing Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ITypeInfo_GetTypeAttr typeInf, pAttr
    GetMem4 ByVal pAttr + &H28, tKind
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
 
    If tKind = TKIND_DISPATCH Then
        Set CreateIDispatch = obj
        Exit Function
    ElseIf tKind <> TKIND_INTERFACE Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ret = CreateStdDispatch(Nothing, obj, typeInf, retObj)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    Set CreateIDispatch = retObj

End Function

' // Create object by Name.
Public Function CreateObjectEx2( _
                ByRef pathToDll As String, _
                ByRef pathToTLB As String, _
                ByRef className As String) As IUnknown
             
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    Dim clsid   As GUID
 
    ret = LoadTypeLibEx(StrPtr(pathToTLB), REGKIND_NONE, typeLib)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    ret = ITypeLib_FindName(typeLib, className, 0, typeInf, 0, 1)
 
    If typeInf Is Nothing Then
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If

    ITypeInfo_GetTypeAttr typeInf, pAttr
 
    GetMem4 ByVal pAttr + &H28, tKind
 
    If tKind = TKIND_COCLASS Then
        memcpy clsid, ByVal pAttr, Len(clsid)
    Else
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If
 
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
         
    Set CreateObjectEx2 = CreateObjectEx(pathToDll, clsid)
 
End Function
             
' // Create object by CLSID and path.
Public Function CreateObjectEx( _
                ByRef path As String, _
                ByRef clsid As GUID) As IUnknown
             
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim isLoad  As Boolean
 
    hLib = GetModuleHandle(StrPtr(path))
 
    If hLib = 0 Then
 
        hLib = LoadLibrary(StrPtr(path))
        If hLib = 0 Then
            Err.Raise 53, , Error(53) & " " & Chr$(34) & path & Chr$(34)
            Exit Function
        End If
     
        isLoad = True
     
    End If
 
    lpAddr = GetProcAddress(hLib, "DllGetClassObject")
 
    If lpAddr = 0 Then
        If isLoad Then FreeLibrary hLib
        Err.Raise 453, , "Can't find dll entry point DllGetClasesObject in " & Chr$(34) & path & Chr$(34)
        Exit Function
    End If

    If Not isInit Then
        CLSIDFromString StrPtr(IID_IClassFactory), iidClsFctr
        CLSIDFromString StrPtr(IID_IUnknown), iidUnk
        isInit = True
    End If
 
    Dim ret     As Long
    Dim out     As IUnknown
 
    ret = DllGetClassObject(lpAddr, clsid, iidClsFctr, out)
 
    If ret = 0 Then

        ret = IClassFactory_CreateInstance(out, 0, iidUnk, CreateObjectEx)
 
    Else
 
        If isLoad Then FreeLibrary hLib
        Err.Raise ret
        Exit Function
     
    End If
 
    Set out = Nothing
 
    If ret Then
 
        If isLoad Then FreeLibrary hLib
        Err.Raise ret

    End If
 
End Function

' // Unload DLL if not used.
Public Function UnloadLibrary( _
                ByRef path As String) As Boolean
             
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim ret     As Long
 
    If Not isInit Then Exit Function
 
    hLib = GetModuleHandle(StrPtr(path))
    If hLib = 0 Then Exit Function
 
    lpAddr = GetProcAddress(hLib, "DllCanUnloadNow")
    If lpAddr = 0 Then Exit Function
 
    ret = DllCanUnloadNow(lpAddr)
 
    If ret = 0 Then
        FreeLibrary hLib
        UnloadLibrary = True
    End If
 
End Function

' // Call "DllGetClassObject" function using a pointer.
Private Function DllGetClassObject( _
                 ByVal funcAddr As Long, _
                 ByRef clsid As GUID, _
                 ByRef iid As GUID, _
                 ByRef out As IUnknown) As Long
             
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = VarPtr(clsid)
    params(1) = VarPtr(iid)
    params(2) = VarPtr(out)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise 5: Exit Function
 
    DllGetClassObject = pReturn
 
End Function

' // Call "DllCanUnloadNow" function using a pointer.
Private Function DllCanUnloadNow( _
                 ByVal funcAddr As Long) As Long
             
    Dim resultCall  As Long
    Dim pReturn     As Variant
 
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
         
    If resultCall Then Err.Raise 5: Exit Function
 
    DllCanUnloadNow = pReturn
 
End Function

' // Call "IClassFactory:CreateInstance" method.
Private Function IClassFactory_CreateInstance( _
                 ByVal obj As IUnknown, _
                 ByVal punkOuter As Long, _
                 ByRef riid As GUID, _
                 ByRef out As IUnknown) As Long
 
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = punkOuter
    params(1) = VarPtr(riid)
    params(2) = VarPtr(out)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    IClassFactory_CreateInstance = pReturn
 
End Function

' // Call "ITypeLib:GetTypeInfoCount" method.
Private Function ITypeLib_GetTypeInfoCount( _
                 ByVal obj As IUnknown) As Long
 
    Dim resultCall  As Long
    Dim pReturn     As Variant

    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeLib_GetTypeInfoCount = pReturn
 
End Function

' // Call "ITypeLib:GetTypeInfo" method.
Private Function ITypeLib_GetTypeInfo( _
                 ByVal obj As IUnknown, _
                 ByVal index As Long, _
                 ByRef ppTInfo As IUnknown) As Long
 
    Dim params(1)   As Variant
    Dim types(1)    As Integer
    Dim list(1)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = index
    params(1) = VarPtr(ppTInfo)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &H10, CC_STDCALL, vbLong, 2, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeLib_GetTypeInfo = pReturn
 
End Function

' // Call "ITypeLib:FindName" method.
Private Function ITypeLib_FindName( _
                 ByVal obj As IUnknown, _
                 ByRef szNameBuf As String, _
                 ByVal lHashVal As Long, _
                 ByRef ppTInfo As IUnknown, _
                 ByRef rgMemId As Long, _
                 ByRef pcFound As Integer) As Long
 
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = StrPtr(szNameBuf)
    params(1) = lHashVal
    params(2) = VarPtr(ppTInfo)
    params(3) = VarPtr(rgMemId)
    params(4) = VarPtr(pcFound)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &H2C, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeLib_FindName = pReturn
 
End Function

' // Call "ITypeInfo:GetTypeAttr" method.
Private Sub ITypeInfo_GetTypeAttr( _
            ByVal obj As IUnknown, _
            ByRef ppTypeAttr As Long)
 
    Dim resultCall  As Long
    Dim pReturn     As Variant
 
    pReturn = VarPtr(ppTypeAttr)
 
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(pReturn), 0)
       
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub

' // Call "ITypeInfo:GetDocumentation" method.
Private Function ITypeInfo_GetDocumentation( _
                 ByVal obj As IUnknown, _
                 ByVal memid As Long, _
                 ByRef pBstrName As String, _
                 ByRef pBstrDocString As String, _
                 ByRef pdwHelpContext As Long, _
                 ByRef pBstrHelpFile As String) As Long
 
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = memid
    params(1) = VarPtr(pBstrName)
    params(2) = VarPtr(pBstrDocString)
    params(3) = VarPtr(pdwHelpContext)
    params(4) = VarPtr(pBstrHelpFile)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &H30, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeInfo_GetDocumentation = pReturn
 
End Function

' // Call "ITypeInfo:ReleaseTypeAttr" method.
Private Sub ITypeInfo_ReleaseTypeAttr( _
            ByVal obj As IUnknown, _
            ByVal ppTypeAttr As Long)
 
    Dim resultCall  As Long
 
    resultCall = DispCallFunc(obj, &H4C, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(ppTypeAttr)), 0)
       
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub
sử dụng nó như sau ... bản thân hàm đó sử dụng tốt ...
tuy nhiên hàm đó sẻ lỗi trong 1 vài trường hợp xx... nếu biết fix lại chút

hãy tự khám phá nó mới vui
Mã:
dim xx As Object
Set XX = CreateObjectEx2("D:\MyDLL.dll","D:\MyDLL.dll", className)

Còn tôi lại ko sử dụng hàm đó ... thế giới code với két nó bao la lắm ... bước ra ngoài kia mới thấy mình
bé bỏng làm sao ??!!! -0-0-0-
 
Lần chỉnh sửa cuối:
Gửi BQT, anh @ptm0412. Nhờ anh cắt từ bài số #43 sang chủ để mới với một cái tên kiểu như là "Cách đăng ký, làm việc với thư viện COM bằng code VBA/VB6" để những ai quan tâm lập trình tập trung trao đổi, còn những ai có nhu cầu ứng dụng như chủ topic này thì vẫn theo topic này thì sẽ trọng tâm hơn. Nếu được vậy em nghĩ sẽ tốt hơn. Cảm ơn anh.
 
Gửi BQT, anh @ptm0412. Nhờ anh cắt từ bài số #43 sang chủ để mới với một cái tên kiểu như là "Cách đăng ký, làm việc với thư viện COM bằng code VBA/VB6" để những ai quan tâm lập trình tập trung trao đổi, còn những ai có nhu cầu ứng dụng như chủ topic này thì vẫn theo topic này thì sẽ trọng tâm hơn. Nếu được vậy em nghĩ sẽ tốt hơn. Cảm ơn anh.
vậy thì cắt hết những gì ko liên quan thớt này đi cho gọn luôn ... nên làm thế
Bài đã được tự động gộp:

Cách cài đặt thư viện "vfpoledb.dll" trong VB6

Khai báo hàm API:
Tôi dùng unicode nên code sẽ dài hơn chút nhưng sẽ an toàn nếu đường dẫn file DLL chứa ký tự có dấu.
C#:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteW" (ByVal hwnd As Long, _
                                                                               ByVal lpOperation As String, _
                                                                               ByVal lpFile As String, _
                                                                               ByVal lpParameters As String, _
                                                                               ByVal lpDirectory As String, _
                                                                               ByVal nShowCmd As Long) As Long

Lệnh chạy install:

C#:
Private Sub InstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
   'Đường dẫn DLL tùy bạn chọn. Nếu lấy từ chính file exe đang chạy thì là:  App.Path & "\vfpoledb.dll"
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll"" /s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Install successful." & vbNewLine & _
               "Application can use classes in this library.", vbInformation
        Unload Me
    End If
End Sub
'-------------------------------------------------------------------------------------
Private Sub UninstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll""  /u/s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Uninstall successful." & vbNewLine & _
               "Application can not use classes in this library.", vbInformation
        Unload Me
    End If
End Sub

Mã nguồn trên là VB6 nhưng dùng mẫu định dạng C# của GPE cho đẹp. Các bạn không nhầm lẫn loại code nhé.
bài này cũng nên cắt đi + nhiều bài khác cho công = he .... cho vào thớt đăng ký nó mới phù hợp
 
Lần chỉnh sửa cuối:
vậy thì cắt hết những gì ko liên quan thớt này đi cho gọn luôn ... nên làm thế
Bài đã được tự động gộp:


bài này cũng nên cắt đi + nhiều bài khác cho công = he .... cho vào thớt đăng ký nó mới phù hợp

Thì chính là từ bài #43 đó.
 
trước đó có rồi ... nên làm thế ... dọn sạch đi cho công =
nếu nói thì nói ngay từ đầu còn ko thì nên thôi sẻ tốt hơn

Tôi sống công = và sòng phẳng mọi cái

Chỉ là chuyển nội dung sang một chủ đề mới sẽ khoa học thôi chứ có gì to tát đâu, bất cứ nội dung nào có thể chuyển qua thì chuyển. Đây không phải là vi phạm nội quy và là làm cho nội dung và hướng người tham gia được trọng tâm theo mỗi chủ đề. Không có gì liên quan đến cái gọi là công bằng cả.
 
Chỉ là chuyển nội dung sang một chủ đề mới sẽ khoa học thôi chứ có gì to tát đâu, bất cứ nội dung nào có thể chuyển qua thì chuyển. Đây không phải là vi phạm nội quy và là làm cho nội dung và hướng người tham gia được trọng tâm theo mỗi chủ đề. Không có gì liên quan đến cái gọi là công bằng cả.
thôi ko trình bày qua lại nữa ... hehehehehe
những bài nào ko liên quan thớt này nên chuyển qua thới khác sẻ phù hợp hơn hoặc cho vào thùng Rác tùy mod xử lý
thế thôi -0-0-0-

nếu đã cầm cân thì nên cho nó thăng = ????!!!!
 
Lần chỉnh sửa cuối:
thôi ko trình bày qua lại nữa ... hehehehehe
những bài nào ko liên quan thớt này nên chuyển qua thới khác sẻ phù hợp hơn hoặc cho vào thùng Rác tùy mod xử lý
thế thôi -0-0-0-

nếu đã cầm cân thì nên cho nó thăng = ????!!!!

Tách bài ra là đúng rồi chứ có gì mà lăn tăn, công với chả bằng bạn KM???
Bài chủ thớt thì hỏi về kết nối FoxproDB, thì đã xong tới bài #43, còn sau đó là bàn về mặt kỹ thuật chuyên sâu, không chỉ áp dụng cho thư viện Foxpro mà còn các thư viện khác cùng cách làm thì nên tạo bài mới để thảo luận nó tập trung hơn chứ có vấn đề gì ở đây nhỉ!
 
Tách bài ra là đúng rồi chứ có gì mà lăn tăn, công với chả bằng bạn KM???
Bài chủ thớt thì hỏi về kết nối FoxproDB, thì đã xong tới bài #43, còn sau đó là bàn về mặt kỹ thuật chuyên sâu, không chỉ áp dụng cho thư viện Foxpro mà còn các thư viện khác cùng cách làm thì nên tạo bài mới để thảo luận nó tập trung hơn chứ có vấn đề gì ở đây nhỉ!
thì cứ cho là từ 43 đi ... còn sau bài đó sao ko nói ... ai thèn lăn tăn
còn vấn đề gì ở đây nhỉ! ... thong thả sẻ hiểu thôi :p

chốt lại Mạnh dừng ở đây he
 
Lần chỉnh sửa cuối:
Web KT
Back
Top Bottom