VBA如何判斷一個Activex Ocx控件或Dll有否注冊

2017-09-09 14:07:00
zstmtony
原創
3694

在Access或Excel中使用Activex控件比較不方便的地方是需要先安裝Activex控件,可以做個安裝程序自動來安裝這些控件,但Access或Excel VBA在啟動時能否自動判斷 一下,指定的Activex 控件(微軟的OCX控件或第三方的OCX控件,甚至DLL)有否在系統中正常注冊了,如果已經安裝并注冊了,就不需要調用安裝程序,如果沒有注冊,就自動打開安裝程序安裝一次

我們的Access通用開發平臺就是使用這種方法來判斷的


那VBA如何判斷一個Activex Ocx控件或Dll有否注冊呢? 我能想到的有幾種方法


1.最粗暴的方法就是創建ocx或dll對象看看有否出錯

如果不提示錯誤就說明控件存在并注冊了,否則就是沒有注冊,即使用錯誤處理方法來判斷

需要先知道控件的類名,這個在控件屬性中很容易查到


on error resume next

dim objTmp as object

set objTmp=createobject("庫名.類名")

if objTmp=nothing then 
    msgbox "未注冊"
else
    msgbox "已注冊"
end if
但這種辦法偶爾會失效的。并不是非常穩定可靠


2.從系統注冊表中查看ocx控件或dll對象對應的注冊表 ClassID或CLSID是否正確


原理:OCX文件是一個動態鏈接庫(其實COM組件就是DLL),regsvr32做的只是加載這個文件,然后調用其中的DllRegisterServer函數,所有的注冊操作其實是在組件自身的DllRegisterServer函數中進行的,也就是說,其實并不知道DllRegisterServer到底做了什么操作,如果想判斷一個組件是否已經注冊如果知道這個組件中的某個對象的ClassID或者ProgID。那直接在注冊表的HKEY_CLASSES_ROOT\CLSID鍵中查找ClassID或在HKEY_CLASSES_ROOT鍵中查找ProgID就可以了,如果找到就表明已經注冊了。

還有要注意版本問題,也就是說,如果做了二進制兼容,可能是新舊版本用的是同一個ClassID.在注冊表HKEY_CLASSES_ROOT\CLSID鍵中查找HKEY_CLASSES_ROOT\CLSID\{.....}\InprocServer32默認值是這個組件文件路徑的CLSID就是你要找的。

首先大家要先在網上找一個注冊表讀寫的類,這個百度一下,非常多,代碼比較長,這里就不多說了,只列出關鍵的代碼


'通過注冊表的ClsId來檢查ActiveX是否正常注冊
Public Function gf_CheckOcxByClsId(strClsIdOrName As String, Optional intType As OcnCheckOcxType = ocnCheckClassId, Optional strRegValue As String = "", Optional lngKey64Or32 As RegReadWOW64Constants = KEY32) As Boolean
  If intType = ocnCheckClassId Then
      Dim clsRegEdit As New clsSysRegEditNew
        Dim strReg As String
        gf_CheckOcxByClsId = False
        'strReg = clsRegEdit.GetString(HKEY_CLASSES_ROOT, "CLSID" & strClsIdOrName & "\ProgID", "")
        Dim lngRtn As Long
        With clsRegEdit
             'Access交流網通用開發平臺的注冊表處理類
             .OpenKey HKCR, "CLSID" & strClsIdOrName & "\ProgID", lngKey64Or32
            lngRtn = .SystemError()
            If lngRtn = 0 Then
             strReg = .QueryValue("")  '取默認值 節點值
            End If
            .CloseKey
            
        End With
        
        If strReg <> "" Then
           If strRegValue <> "" Then
             If strReg = strRegValue Then
                gf_CheckOcxByClsId = True
             End If
           Else
             gf_CheckOcxByClsId = True
           End If
        End If
       Set clsRegEdit = Nothing
  Else
     If CheckOcxByClsName(strClsIdOrName) Then
         gf_CheckOcxByClsId = True
     End If
  End If
End Function


相關知識:

判斷 Activex ocx控件或dll是否注冊的相關辦法


使用錯誤處理
set obj=createobject("project1.class1")
能創建的就可以

或者找注冊表
注冊表中的信息
當一個組件注冊后,我們就可以通過前期綁定或者后期綁定來使用。事實上,組件注冊后會在注冊表中寫入大量的信息,理解這些,對于后面的章節都有很大的幫助

當一個組件注冊后,比如該組件的工程名project,類名class1,會在注冊表中的以下位置出現:
HKEY_CLASSES_ROOT\project.class1和HKEY_CLASSES_ROOT\CLSID

在HKEY_CLASSES_ROOT\project.class1這個鍵下面,會看到Clsid子項。而這個子項會出現在HKEY_CLASSES_ROOT\CLSID下面,從而使兩部分相聯系起來。
這個主要是為了OLE和早期COM的兼容。

還有HKEY_CLASSES_ROOT\TypeLib和HKEY_CLASSES_ROOT\Interface

看看HKEY_CLASSES_ROOT\CLSID下面,找到我們剛才在HKEY_CLASSES_ROOT\
project.class1看到的Clsid,比如是{A85899CB-A752-40AA-9F38-DCC4384C5EBD}
我們對下面的一些子項進行說明,請注意根據組件的不同,子項也會有不同
ProgID:程序標志,由項目名稱和類名兩部分組成。如: project.class1
LocalServer32:進程外組件,如ActiveX EXE這樣的進程外服務器中的組件需要該子鍵
該子鍵保存了服務器文件的物理路徑。
InprocServer32:進程內組件,如ActiveX DLL這樣的進程內服務器中的組件需要該子鍵
該子鍵保存了服務器文件的物理路徑。
TypeLib:類型庫。它所對應的數據在HKEY_CLASSES_ROOT\TypeLib下面互相聯系。
Vb的工程->引用對話框,就是通過該鍵來填充列表的。

分享
北京十一选五基本走势