我以为,调用 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);
我通过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);
解决方案 »
- 请教如何通过socket分别用两个线程 先发送数据 后接受数据
- 做过IE MIME过滤的朋友帮忙看下,中国雅虎首页的flash出不来
- 本科毕业两年8k在北京是什么水平
- 如何填充一个五角星线形?
- 图形可以正确预览,但是打印完成以后图形以非常小的大小出现在纸的最左下角
- 如何使用(设置)虚拟列表(virtual list)?
- 怎样在一个button上当鼠标移动到上面的时候有个tip提示?
- combobox的奇怪问题
- 用CLASSWIZD在DLL中加了一个CDIALOG子类MYDIALOG,为什么看不见??
- picture控件重绘问题!我急死了。
- 怎么做带多个对话框的插件?
- 有关ISKINDOF() 函数的问题
看看微软的MediaPlayer Sdk中的一个例子,里面 有动态创建 MediaPlayer 的
例子,
我认为只要是WINDOWS的东西都不能绕过注册表的
在一个表中利用主键去搜索一条记录一样
CLSID就是它的主键。CLSID就是COM Persistent化的结果。也可以这么说,CLSID就是COM组件与外界唯一的接口。还可以说,世界上没有任何东西是完全自包含的。"如果一个东西自身没有可以标识自己的,把自己和其他东西区别开来的指标,那么它就不存在."----挺唯心 呵呵
还有activex只是一种技术,我们所用的ocx控件,他只有在相应的环境下
才能够使用,就象win程序在windows下使用一样,他不能脱离windows环境
注册,就是告诉环境该控件的存在,使该控件能够在相应的环境下运行!
调用 ActiveX组件的过程,应该是根据ProgID到注册表寻找到组件的路径,然后加载文件,调用其方法和属性。那么,如果知道组件的路径,应该可以绕过注册表,直接调用组件。
这是没有错!不过微软改进了这一做法!
同时,IDispatch是实现自动化的核心!为了让客户端更方便的实现,它通过注册表来完成,所以 Analyst() 说invoke函数的实现一般是载入类型库,根据名字查询得到分发ID,所以如果你注册表里不注册组件的话,类型库就找不到了。是对的!
下面是一个例子:
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);
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 的区别