VBA如何判断一个Activex Ocx控件或Dll有否注册

2017-09-09 14:07:00
zstmtony
原创
173

在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的工程->引用对话框,就是通过该键来填充列表的。

分享