每个ActiveX Dll都应该有个DllGetClassObject函数,利用该函数就可以直接创建所需的com对象,而不需要通过注册表(或者注册),
STDAPI DllGetClassObject(
REFCLSID rclsid, //CLSID for the class object
REFIID riid, //Reference to the identifier of the interface
// that communicates with the class object
LPVOID * ppv //Address of output variable that receives the
// interface pointer requested in riid
);
这里必须知道两样东西,一个rclsid,就是需要创建的com对象的CLSID,另一个是 riid,该对象的一个接口的 id.
然而,调用DllGetClassObject,并不能直接创建所需要的对象,但可以得到对应的 IClassFactory,再由 IClassFactory.CreateInstance得到所需的对象.
vb实现代码大概如下:
需要用到一个库,http://www.mvps.org/emorcillo/download/vb6/tl_ole.zip
(引用页,http://www.mvps.org/emorcillo/en/code/vb6/wbframe.shtml)
另外,也将那个ActiveX Dll引用进工程,这里,并不是需要注册它,而是为了方便使用它的方法,因为并没有使用new来创建对象,
程序编译后即使不注册那个Dll文件都能够正常使用.
Option Explicit
''假设ActiveX Dll 的文件名为dllDemo.dll,并且处于工程同一目录
Private Declare Function DllGetClassObject Lib "dllDemo.dll" ( _
rclsid As UUID, riid As UUID, ByRef ppv As Any) As Long
''class id
Private Const ClsStr_Obj As String = "{C1A334BA-D1A4-48D0-98D5-47FE934961DF}"
''接口id
Private Const IidStr_Ins As String = "{231114D5-E046-4DAE-B192-0AB49D493A85}"
''IClassFactory id
Private Const strIID_IClassFactory As String = "{00000001-0000-0000-C000-000000000046}"
Private ClsId_Obj As UUID
Private Iid_Ins As UUID
Private iid_iunknow As UUID
Private iid_iclassfactory As UUID
Private Sub Command1_Click()
Dim tobj As olelib.IUnknown
Dim tobj2 As dllDemo.IDemo
Dim tFac As olelib.IClassFactory
Call DllGetClassObject(ClsId_Obj, iid_iclassfactory, tFac)
tFac.CreateInstance Nothing, iid_iunknow, tobj
Set tFac = Nothing
Set tobj2 = tobj
''调用IDemo.Test测试所创建的对象
tobj2.Test
End Sub
Private Sub Form_Load()
''将string转换为 UUID
CLSIDFromString ClsStr_Obj, ClsId_Obj
CLSIDFromString IidStr_Ins, Iid_Ins
CLSIDFromString IIDSTR_IUnknown, iid_iunknow
CLSIDFromString strIID_IClassFactory, iid_iclassfactory
End Sub
至此,问题似乎已经解决了,只要为不同的ActiveX Dll编写对应的DllGetClassObject函数就可以了,只是当文件名未定时就比较难办了,例如编写插件时.
解决办法是用LoadLibrary动态的调用各个dll上的DllGetClassObject.可惜的是vb不支持函数指针.我的办法是借助vc来解决.用vc写dll供vb调用,主要代码如下:
// CrCom.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <unknwn.h>
#include <objbase.h>
typedef int (CALLBACK *MYPROC)(REFCLSID,REFIID,LPVOID *);
BOOL APIENTRY DllMain( HANDLE hModule,