MFC程序运行时注册自身所需要的COM组件
2012-12-27 19:23
253 查看
我们可以在网上找到很多开发好的COM组件,这些组件提供了接口,我们可以对其进行二次开发,比如mp3play.ocx,通过这个控件,我们可以简单快速开发出自己的MP3播放器,COM组件可以是.ocx后缀,也可以是.dll后缀。熟悉VB开发的同志们对这些控件应该很熟悉吧。这些控件不仅可以用在VB中,同样可以用在VC等开发环境中。
在使用该控件时应该保证该电脑上已经注册了该控件。通常,我们都是通过安装包程序来调用regsvr32注册我们程序需要的控件。但由于我们开发的仅仅是只有一个exe和一个ocx的小程序,还要打包成安装包,未免太麻烦了。那么我们能不能在程序中加入代码,在刚运行时就注册该控件呢?答案当然是肯定的,不然就不会有那么多绿色软件了。
一开始我想到在程序中的InitInstance( );初始化实例函数中进行注册,写在构造窗体前,检测当前文件夹下是否有我们需要的控件,如果没有则直接MessageBox提示后退出程序。如果有的话用ShellExecute函数调用系统中的regsvr32.exe来注册我们的ocx控件。但是代码写好后,测试一下,暴露出一些问题,在没有注册过控件的电脑上运行时,出现了问题,DeBug版本下弹出错误提示然后程序崩溃退出。Release版本下双击无反应。我研究了好几个小时,无论把注册ocx的代码放到InitInstance(
)最前端还是放到窗体构造函数中,还是放到程序实例构造函数中。结果都是一样,依然存在问题。
仔细思考了一下,我们的程序在编译时,控件就已经拖到窗体中了,它已经静态的躺在资源里了,程序首次运行时,由于程序已经运行了,静态资源已经读入了内存,后来才进行注册,而我们的程序不知道系统中后来又注册了这个控件了,就出错了。
但后来我尝试不在编译时把控件拖到窗体上,而是通过代码,用new运算符创建一个ocx对应的类的对象,然后用该类提供的create( )函数在窗体上构造出该控件。但是运行时还是遇到一样的问题。不过有了改善,之前是一运行就崩溃,这样写以后,只是首次运行崩溃,再次双击运行就正常了。
经过我反复的试验,发现,在程序上添加一个按钮,程序运行后再单击这个按钮,这个按钮对应的响应函数中用new运算符创建一个ocx对应的类的对象,然后用该类提供的create( )函数在窗体上构造出该控件。这样,再也没出现崩溃的问题了。但是这样做明显太别扭,不可采用。
后来无意中在一本VC++实例的书上看到了有关COM组件的注册于卸载。我的问题终于圆满的解决了。书上是这样讲的。用LoadLibrary函数装载控件库文件,然后用GetProAddress函数检索指定的动态库中输出的库函数地址,然后调用该库函数。以注册mp3play.ocx为例。在程序InitInstance( )函数中构造窗体前加入这段代码:
注意,如果GetProAddress函数返回了空地址,则注册失败。
卸载该控件时,把第二行代码中的DllRegisterServer改为DllUnRegisterServer即可。
在没有注册过该控件的电脑上运行,一次成功,没有出现过崩溃问题了。愁眉总算舒展了。问题完美解决,并且我们可以直接把控件拖到界面上了,也不用new运算符和create( )函数来构造控件实例了。
在使用该控件时应该保证该电脑上已经注册了该控件。通常,我们都是通过安装包程序来调用regsvr32注册我们程序需要的控件。但由于我们开发的仅仅是只有一个exe和一个ocx的小程序,还要打包成安装包,未免太麻烦了。那么我们能不能在程序中加入代码,在刚运行时就注册该控件呢?答案当然是肯定的,不然就不会有那么多绿色软件了。
一开始我想到在程序中的InitInstance( );初始化实例函数中进行注册,写在构造窗体前,检测当前文件夹下是否有我们需要的控件,如果没有则直接MessageBox提示后退出程序。如果有的话用ShellExecute函数调用系统中的regsvr32.exe来注册我们的ocx控件。但是代码写好后,测试一下,暴露出一些问题,在没有注册过控件的电脑上运行时,出现了问题,DeBug版本下弹出错误提示然后程序崩溃退出。Release版本下双击无反应。我研究了好几个小时,无论把注册ocx的代码放到InitInstance(
)最前端还是放到窗体构造函数中,还是放到程序实例构造函数中。结果都是一样,依然存在问题。
仔细思考了一下,我们的程序在编译时,控件就已经拖到窗体中了,它已经静态的躺在资源里了,程序首次运行时,由于程序已经运行了,静态资源已经读入了内存,后来才进行注册,而我们的程序不知道系统中后来又注册了这个控件了,就出错了。
但后来我尝试不在编译时把控件拖到窗体上,而是通过代码,用new运算符创建一个ocx对应的类的对象,然后用该类提供的create( )函数在窗体上构造出该控件。但是运行时还是遇到一样的问题。不过有了改善,之前是一运行就崩溃,这样写以后,只是首次运行崩溃,再次双击运行就正常了。
经过我反复的试验,发现,在程序上添加一个按钮,程序运行后再单击这个按钮,这个按钮对应的响应函数中用new运算符创建一个ocx对应的类的对象,然后用该类提供的create( )函数在窗体上构造出该控件。这样,再也没出现崩溃的问题了。但是这样做明显太别扭,不可采用。
后来无意中在一本VC++实例的书上看到了有关COM组件的注册于卸载。我的问题终于圆满的解决了。书上是这样讲的。用LoadLibrary函数装载控件库文件,然后用GetProAddress函数检索指定的动态库中输出的库函数地址,然后调用该库函数。以注册mp3play.ocx为例。在程序InitInstance( )函数中构造窗体前加入这段代码:
HINSTANCE h; h = ::LoadLibrary(_T("Mp3play.ocx")); FARPROC pFunc = ::GetProcAddress((HMODULE)h,"DllRegisterServer"); if (pFunc==NULL) { ::MessageBox(NULL,_T("OCX控件加载失败!"),_T("错误"),MB_ICONERROR); return FALSE; } pFunc();
注意,如果GetProAddress函数返回了空地址,则注册失败。
卸载该控件时,把第二行代码中的DllRegisterServer改为DllUnRegisterServer即可。
在没有注册过该控件的电脑上运行,一次成功,没有出现过崩溃问题了。愁眉总算舒展了。问题完美解决,并且我们可以直接把控件拖到界面上了,也不用new运算符和create( )函数来构造控件实例了。
相关文章推荐
- 避免在MFC程序中调用进程外Com组件出现“由于另一个程序正在运行...”的解决方案
- 程序运行时 0xC0000005: 读取位置 0x00000000 时发生访问冲突 ,可能是 com 组件引入各种问题
- 解决:ASP.NET 4.5尚未在Web服务器上注册。您需要手动将Web服务器配置为使用ASP.NET 4.5,这样您的网站才能正确运行。
- mfc编写的程序如何在别人机器上运行?
- MFC设置程序以管理员权限运行
- 让MFC程序隐藏运行界面
- OSX10.10系统下AICS6您需要安装旧 Java SE 6 运行环境才能打开程序
- 在Windows Server 2008 X64中通过.NET程序调用32位com组件
- 注册COM组件
- vs2005 转到 vs2008 运行:未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序。
- 运行此安装程序之前,必须安装 32 位 Windows 映像处理组件(WIC)解决办法
- VS2008中编译运行MFC应用程序时,出现无法启动程序,因为计算机中丢失mfc90ud.dll的解决方案
- vs2012编译xp运行的mfc程序InitializeCriticalSectionEx解决方案
- 转载:如何指定程序在Vista上面需要提升权限运行(Elevated)
- 让MFC程序隐藏运行界面
- IDE-----VS2005运行过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的解决
- win7 2008 尚未在 Web 服务器上注册ASP.NET 4.0。为了使网站正确运行,可能需要手动将 Web 服务器配置为使用 ASP.NET 4.0,按 F1 可了解更多详细信息。
- Windows7,程序兼容助手:这个程序可能安装不正确(做注册表里设置白名单,软件自身的名字不能带setup)
- 如何注册.net 的类库dll 为com组件
- c#程序在部分电脑运行异常解决方法(System.Runtime.InteropServices.COMException (0x80070422): 无法启动服务)