我以为,调用 ActiveX组件的过程,应该是根据ProgID到注册表寻找到组件的路径,然后加载文件,调用其方法和属性。那么,如果知道组件的路径,应该可以绕过注册表,直接调用组件。
我通过LoadLibrary加载dll文件,然后通过DllGetClassObject成功的找到了组件的接口,但在使用invoke时,出现库没有注册的错误,究竟是为什么?组件调用的真正过程是什么?
以下是我的代码:(其中qmail.dll是我以前做的组件,组件本身没有问题,但我在调试下面的代码时,有意使它不注册)
 CoInitialize(NULL);
// TODO:在此添加额外的初始化代码

    CLSID clsID;
USES_CONVERSION;
CLSIDFromString(A2W("{E2F1F220-89BC-4E36-9E19-60383691E69E}"),&clsID);typedef LONG (WINAPI *MYPROC)(REFCLSID,REFIID,LPVOID*); 
IClassFactory* iclass;
IDispatch* qupload;
MYPROC myproc;
HMODULE hin=LoadLibrary("qmail.dll");
myproc=(MYPROC)GetProcAddress(hin,"DllGetClassObject");
HRESULT hr= myproc(clsID,IID_IClassFactory,(void**)(&iclass));
hr=iclass->CreateInstance(NULL,IID_IDispatch,(void**)&qupload);
iclass->Release();
DISPPARAMS dispparamsNoArgs;
VARIANT temp1[1];
temp1[0].vt=VT_BYREF|VT_VARIANT;
temp1[0].pvarVal=&CComVariant("jjjjjjj");   //这句为了调试,随便写的
dispparamsNoArgs.rgvarg=temp1;
dispparamsNoArgs.cArgs=1;
dispparamsNoArgs.cNamedArgs=0;
VARIANT var1;
hr=qupload->Invoke(0x2,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_PROPERTYGET,&dispparamsNoArgs,&var1, NULL, NULL);
CoFreeLibrary(hin);

解决方案 »

  1.   

    http://expert.csdn.net/Expert/topic/1301/1301394.xml?temp=.2142603
     看看微软的MediaPlayer Sdk中的一个例子,里面 有动态创建 MediaPlayer 的
    例子,
      

  2.   

    我也想知道这个问题的答案
    我认为只要是WINDOWS的东西都不能绕过注册表的
      

  3.   

    注册表只是一个数据库而已,究竟ActiveX组件调用的实质在那里?
      

  4.   

    ActiveX调用过程就好像
    在一个表中利用主键去搜索一条记录一样
    CLSID就是它的主键。CLSID就是COM Persistent化的结果。也可以这么说,CLSID就是COM组件与外界唯一的接口。还可以说,世界上没有任何东西是完全自包含的。"如果一个东西自身没有可以标识自己的,把自己和其他东西区别开来的指标,那么它就不存在."----挺唯心  呵呵
      

  5.   

    注册只是为了便于管理!
    还有activex只是一种技术,我们所用的ocx控件,他只有在相应的环境下
    才能够使用,就象win程序在windows下使用一样,他不能脱离windows环境
    注册,就是告诉环境该控件的存在,使该控件能够在相应的环境下运行!
      

  6.   

    invoke函数的实现一般是载入类型库,根据名字查询得到分发ID,所以如果你注册表里不注册组件的话,类型库就找不到了。
      

  7.   

    我又查了一下资料:
    调用 ActiveX组件的过程,应该是根据ProgID到注册表寻找到组件的路径,然后加载文件,调用其方法和属性。那么,如果知道组件的路径,应该可以绕过注册表,直接调用组件。
    这是没有错!不过微软改进了这一做法!
    同时,IDispatch是实现自动化的核心!为了让客户端更方便的实现,它通过注册表来完成,所以 Analyst() 说invoke函数的实现一般是载入类型库,根据名字查询得到分发ID,所以如果你注册表里不注册组件的话,类型库就找不到了。是对的!
      

  8.   

    问题是,如果invoke一定要通过注册表来实现。那么,在得到注册表信息以后,windows做了写什么,是如何做的?
      

  9.   

    问题的关键是com技术里的自动化的是通过clsid来实现的!
      

  10.   

    invoke()的第一个参数决定了invoke的行为,它要求传入一个我称为disoid,这个dispid是一个长整数,它标识一个函数!对于某一个特定实现,dispid是唯一的,所以我在上面说它是clsid(当然这个说法不正确)。
    下面是一个例子:
    DISPID dispid;
    OLECHAR* name=L"fx"           fx为一个函数名
    pIDispatch->GetIDsOfNames(IID_NULL,&name,1,GetUserDefaultLCID(),&dispid);
    DISPPARAMS dispparamsNoArgs={null,null,0,0};
    pIDispatch->Invoke(dispid,IID_NULL,GetUserDefaultLCID(),DISPATCH_METHOD,&dipparamsNoArgs,NULL,NULL,NULL);
      

  11.   

    Invoke方法的实现(或IDispatch接口)与windows或COM库无关,你可以用简单的switch来实现,也可以象MFC一样基于表格,向ATL那样读取并分析类型库
      

  12.   

    把<atlcom.h>文件中
    protected:
    _tihclass _tih;
    改成
    _tihclass _tih;
    protected:然后把你的DllGetClassObject函数改成如下
    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
    {
    HRESULT hr = _AtlModule.DllGetClassObject(rclsid, riid, ppv);
    if (SUCCEEDED(hr))
    {
    CComObject< YourClalss>* pObject = (CComObject< YourClass >*) ppv;
    CComTypeInfoHolder* pHolder = &pObject->_tih;
    pHolder->m_plibid = &LIBID_YourLib;
    pHolder->m_wMajor = 0xFFFF;
    pHolder->m_wMinor = 0xFFFF; hr = pHolder->GetTI( GetUserDefaultLCID() );
    }
    return hr;
    }我没测试,你编译后试试。调用 ActiveX组件的过程是
    ...
    根据ProgID到注册表寻找到组件的路径,然后加载文件,创建对象,装载对象类型信息,调用其方法和属性。
    一般在第一次调用invoke或GetIDsOfNames时装载对象类型信息。以上方法是在创建对象时装载对象类型信息
    ...有空的话可以看一看 CComTypeInfoHolder::GetTI(LCID lcid) //在<atlcom.h>文件中
    注意其中两个函数 LoadTypeLib 和 LoadRegTypeLib 的区别
      

  13.   

    http://expert.csdn.net/Expert/TopicView1.asp?id=1417437帮忙