欢迎光临
我们一直在努力

不注册调用ActiveX Dll-.NET教程,评论及其它

建站超值云服务器,限时71元/月

每个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,
                       dword  ul_reason_for_call,
                       lpvoid lpreserved
      )
{
    return true;
}

// if(riid==null)riid=&iid_iunknown
int _stdcall crcomobj(
      lpcstr lpdll,
      clsid *rclsid,
      iid *riid,
      lpvoid * ppv)
{
 hinstance hinstlib;
    myproc procadd;  

 bool ffreeresult, fruntimelinksuccess = false;
 int rtn=0;
 // get a handle to the dll module.
 
 
    hinstlib = loadlibrary(lpdll);
 
    // if the handle is valid, try to get the function address.
 
    if (hinstlib != null)
    {   
        procadd =(myproc)getprocaddress(hinstlib, “dllgetclassobject”);
 
        // if the function address is valid, call the function.
  
        if (fruntimelinksuccess = (procadd != null))
  {  
   if(rclsid==null)
   {
    freelibrary(hinstlib);
    return 0;
   }
   
   if(riid==null)
    riid=(iid *)&iid_iunknown;

   iclassfactory *pif;
   pif=null;
            if(procadd(*rclsid,iid_iclassfactory,(void **)&pif)==s_ok && pif!=null)
   {
    if(pif->createinstance(null,*riid,ppv)==s_ok)
     rtn=(int)hinstlib;    
    pif->release();
    pif=null;
   }
  }
        // free the dll module.
 
        if(!rtn)ffreeresult = freelibrary(hinstlib);
    }
 return rtn;
}

// if strriid==null, use iid_iunknown;
int _stdcall crcomobj2(
      lpcstr lpdll,
      lpcstr  strrclsid,
      lpcstr  strriid,
      lpvoid * ppv )
{
 hinstance hinstlib;
    myproc procadd;  

 bool ffreeresult, fruntimelinksuccess = false;
 
 int rtn=0;
 // get a handle to the dll module.
 
 
    hinstlib = loadlibrary(lpdll);
 
    // if the handle is valid, try to get the function address.
 
    if (hinstlib != null)
    {   
        procadd =(myproc)getprocaddress(hinstlib, “dllgetclassobject”);
 
        // if the function address is valid, call the function.
 
        if (fruntimelinksuccess = (procadd != null))
  {  
   clsid rclsid;
   iid riid;
   
   if(strrclsid==null)
   {
    freelibrary(hinstlib);
    return 0;
   }
   clsidfromstring((lpolestr )strrclsid,&rclsid);

   if(strriid!=null)
    clsidfromstring((lpolestr )strriid,&riid);
   else
    riid=iid_iunknown;

   iclassfactory *pif=null;

            if(procadd(rclsid,iid_iclassfactory,(void **)&pif)==s_ok && pif!=null)
   {
    if(pif->createinstance(null,riid,ppv)==s_ok)
     rtn=(int)hinstlib;    
    pif->release();
    pif=null;
   }
  }
        // free the dll module.
  
        if(!rtn)ffreeresult = freelibrary(hinstlib);
    }
 return rtn;
}

在vb中的使用方法,crcomobj传递的是uuid,crcomobj2传递的是string,

函数声明
private declare function crcomobj lib “crcom.dll” ( _
    byval lpdll as string, byval rclsid as long, byval riid as long, byref ppv as any) as long
private declare function crcomobj2 lib “crcom.dll” ( _
    byval lpdll as string, byval strrclsid as long, byval strriid as long, byref ppv as any) as long

dim tobj as olelib.iunknown
dim tobj2 as dlldemo.idemo

hlib = crcomobj(app.path & “\dlldemo.dll”, varptr(clsid_obj), 0, tobj)
set tobj2 = tobj
tobj2.test

或者

hlib=crcomobj2(app.path & “\dlldemo.dll”, strptr(clsstr_obj), 0, tobj)
set tobj2 = tobj
tobj2.test

crcomobj与crcomobj2返回的是loadlibrary的返回值,必要的时候需要用freelibrary释放.

后记:
我的多页面浏览器le中,也实现了不注册调用activex dll,我是直接使用了一本书(advanced visual basic)的代码,代码颇长,似乎也挺复杂,原先使用的时候也不明所以然,后来终于搞清楚了,其原理是一样的,但是因为vb不支持函数指针,于是它花了很大力气去处理这个问题.相比而言,我觉得还是借用一下vc比较好,这样的话简捷的多.

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 不注册调用ActiveX Dll-.NET教程,评论及其它
分享到: 更多 (0)