本文在《VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程》基础改造而来,也参考了《如何制作CAB包》,做一个简单ocx示例。
最近在弄ocx控件发布到网站上使用,就是用户在使用过程中,自动下载安装ocx控件。 ActiveX控件用于Web的过程是将控件嵌入主页中,用户通过浏览器访问该主页时,将主页中的控件下载, 并在用户机器上注册,以后就可在用户的浏览器上运行。控件下载一次后就驻留在用户本地机器上,下次 再访问相同的主页时,可不再下载该控件,而是直接运行用户本地的控件。这里控件容器就是浏览器,用 户不需要通过浏览器调用控件的属性或方法。因此,开发面向Web的ActiveX控件比开发桌面的控件还要简 单些,所复杂的是如何将该控件很好地嵌入主页,使用户能正常浏览。
一. 创建MFC ActiveX项目
1. 打开VS2005新建MFC项目。这里我们取名为“ActiveXDemo”。
2. 输入项目名称为“ActiveXDemo”和项目位置。点击“确定”按钮,打开向导对话框。
3. 选择“控件设置”选项卡,具体设置可参考上图。其它选项卡为默认设置。最后点击“完成”按钮保存设置。
二. 添加控件方法
VC2005会为我们自动创建好MFC ActiveX程序框架,我们只要给该ActiveX控件添加方法即可。现在我们给控件添加一个“AddFun”方法,这个方法是将两个数相加并返回结果。
1. 点击“视图”,打开“类视图”窗口。
2. 展开“ActiveXDemoLib”项,选中“_DActiveXDemo”项。点击鼠标右键,选择“添加”下的“添加方法”。
3. 打开添加方法向导窗口。因为我们是添加一个加法方法,所以我们设置的返回类型为LONG型,方法名设为AddFun,添加两个LONG类型参数Add1,Add2。
5. 打开代码视图,我们会发现VC2005已经为我们添加了一个“AddFun”方法,我们在方法内添加“return Add1 + Add2;”语句。
三、MFC Activex 安全问题
1、在默认环境下,编译的MFC Activex控件,只能在本地代码中运行,即在http://localhost/xxx/xxx.htm中执行,而在http://127.0.0.1/xxx/xxx.htm中提示无相关属性,需要设置其初始化和脚本运行的安全性。
ActiveX在远程IE页面上执行,需要实现安全接口。
在ATL写的ActiveX中,用IObjectSafety。
http://support.microsoft.com/kb/168371/en-us
在MFC写的ActiveX中,直接修改注册表。
http://support.microsoft.com/kb/161873/en-us
mfc实现的ocx,要在app实现文件中包括两个文件:并重写DllRegisterServer和DllUnregisterServer方法。重写后的代码如下:ActiveXDemo.cpp
#include "stdafx.h" #include "ActivexDemo.h" #include <comcat.h> #include <objsafe.h> #ifdef _DEBUG #define new DEBUG_NEW #endif CActiveXDemoApp theApp; const GUID CDECL BASED_CODE _tlid = {0x3332A68D,0xAB57,0x4577,{0x82,0x16,0xCC,0x09,0xE0,0x0F,0x41,0x90}};//此处是ActiveXDemo.idl中uuid的16进制数组 //{ 0x344B8576, 0xAB2C, 0x4D38, { 0xAE, 0x7, 0x73, 0x74, 0x22, 0x89, 0x72, 0xEA } }; const WORD _wVerMajor = 1; const WORD _wVerMinor = 0; // CActiveXDemoApp::InitInstance - DLL 初始化 BOOL CActiveXDemoApp::InitInstance() { BOOL bInit = COleControlModule::InitInstance(); if (bInit) { // TODO: 在此添加您自己的模块初始化代码。 } return bInit; } // CActiveXDemoApp::ExitInstance - DLL 终止 int CActiveXDemoApp::ExitInstance() { // TODO: 在此添加您自己的模块终止代码。 return COleControlModule::ExitInstance(); } // 创建组件种类 HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription) { ICatRegister* pcr = NULL ; HRESULT hr = S_OK ; hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr); if (FAILED(hr)) return hr; // Make sure the HKCR\Component Categories\{..catid...} // key is registered. CATEGORYINFO catinfo; catinfo.catid = catid; catinfo.lcid = 0x0409 ; // english // Make sure the provided description is not too long. // Only copy the first 127 characters if it is. int len = wcslen(catDescription); if (len>127) len = 127; wcsncpy(catinfo.szDescription, catDescription, len); // Make sure the description is null terminated. catinfo.szDescription[len] = '\0'; hr = pcr->RegisterCategories(1, &catinfo); pcr->Release(); return hr; } // 注册组件种类 HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid) { // Register your component categories information. ICatRegister* pcr = NULL ; HRESULT hr = S_OK ; hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr); if (SUCCEEDED(hr)) { // Register this category as being "implemented" by the class. CATID rgcatid[1]; rgcatid[0] = catid; hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid); } if (pcr != NULL) pcr->Release(); return hr; } // 卸载组件种类 HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid) { ICatRegister* pcr = NULL ; HRESULT hr = S_OK ; hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr); if (SUCCEEDED(hr)) { // Unregister this category as being "implemented" by the class. CATID rgcatid[1] ; rgcatid[0] = catid; hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid); } if (pcr != NULL) pcr->Release(); return hr; } STDAPI DllRegisterServer(void) { HRESULT hr; AFX_MANAGE_STATE(_afxModuleAddrThis); if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE)) return ResultFromScode(SELFREG_E_CLASS); // 标记控件初始化安全. // 创建初始化安全组件种类 hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!"); if (FAILED(hr)) return hr; // 注册初始化安全 hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing); if (FAILED(hr)) return hr; // 标记控件脚本安全 // 创建脚本安全组件种类 hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!"); if (FAILED(hr)) return hr; // 注册脚本安全组件种类 hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting); if (FAILED(hr)) return hr; return NOERROR; } // DllUnregisterServer - Removes entries from the system registry STDAPI DllUnregisterServer(void) { HRESULT hr; AFX_MANAGE_STATE(_afxModuleAddrThis); if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE)) return ResultFromScode(SELFREG_E_CLASS); // 删除控件初始化安全入口. hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing); if (FAILED(hr)) return hr; // 删除控件脚本安全入口 hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting); if (FAILED(hr)) return hr; return NOERROR; }
此处如果复制网上代码不做改动进行build,也能生成ocx,但是vs工具生成ocx后自动注册ocx,将有以下错误提示:
Project : error PRJ0050: Failed to register output. Please try enabling Per-user Redirection or register the component from a command prompt with elevated permissions.
最终导致ocx无法注册成功。
出现以上错误的原因是:
1、win7环境uac设置的原因,要以管理员身份运行cmd。
2、ocx本身依赖的dll缺少。
3、我自己的原因:ActiveXDemo.cpp有一个GUID的实例_tlid,它的值必须为idl文件中uuid的16进制数组形式,否则无法在注册表中注册。
现在控件就可以在自注册时就注册为安全控件了。
3、 最后build项目,ocx控件就产生了。
ActiveX打包
用到的工具:
打包工具iexpress.exe打包文件:
test.html
extadd.inf
ActiveXDemo.ocx
制作步骤
步骤1 准备inf文件
[version] signature="$CHICAGO$" AdvancedINF=2.0 [DefaultInstall] CopyFiles=install.files RegisterOCXs=RegisterFiles [RInstallApplicationFiles] CopyFiles=install.files RegisterOCXs=RegisterFiles [DestinationDirs] install.files = 24,Program Files\extadd [SourceDisksNames] 1=%DiskName%,extadd.cab,1 [install.files] ActiveXDemo.ocx=ActiveXDemo.ocx test.html=test.html [test.html] file-win32-x86=thiscab RegisterServer=no [ActiveXDemo.ocx] file-win32-x86=thiscab RegisterServer=yes clsid={99FFE4AD-6E24-490A-A849-BEFDB9808F11} DestDir=24,Program Files\extadd [RegisterFiles] %24%\Program Files\extadd\ActiveXDemo.ocx
注释:
(1) "thiscab" 是一个关键字,意指包含该INF的CAB文件。也可以从网上下载所需要的DLL文件,只要指定一个HTTP 网址即可。
(2)关键字"file-win32-x86" 指定平台是 x86。
(3)文件版本号可见属性。
(4) "DestDir"指的是装载目录或者文件的地址: 11 指定为系统目录 WINDOWS/ /SYSTEM32;
(5) "clsid" 指的是要安装控件的CLSID。
步骤2 制作CAB
0) 运行iexpress.exe
1) 选择“Create new Self Extraction Directive file”,点击下一步。
2) 选择“Create compressed files only(ActiveX Installs)”,点击下一步。
3) 点击Add,选择所有文件包括inf,点击下一步。
4) 点击Browse,输入.CAB文件的存放地址(包含所取文件名),并且要选中“Store files using Long File Name inside Package”。点击下一步。
5) 选择“Don’t save”,一直点击下一步,直到完成。
遇到的问题
以上制作的ActiveXDemo.ocx,能够在开发环境下注册,并在html页面上调用成功,但是到另外一台没有安装
VS2005的机器进行注册,会注册失败。因为此系统缺少VS2005的运行库,而ActiveXDemo.ocx依赖运行库,所以无法完成注册。VS2005运行库的文件列表如下:
MFC80U.DLL
mfcm80u.dll
msvcm80.dll
msvcp80.dll
msvcr80.dll
Microsoft.VC80.ATL.manifest
Microsoft.VC80.CRT.manifest
Microsoft.VC80.MFC.manifest
需要把这些文件和ActiveXDemo.ocx放在同一目录下,才能找到。
有了这些文件,在没有VS2005的机器上也可以注册成功ActiveXDemo.ocx并进行调用。
赠送一个知识点:可以通过Depends.exe(VC6有带)分析ocx的依赖性和提供的属性、事件、方法等。
Depends.exe可以分析dll依赖的文件,出现黄色问号的为缺少的文件。
编译ocx的release版时可能出现权限不足的问题,是因为缺少VS2005的运行库。可以在编译之前在“属性”中设置不注册ocx,以输出release版本。
相关推荐
总的来说,64位OCX控件打包成CAB和EXE的过程涉及到组件压缩、安全签名、安装脚本编写等多个环节,这对于开发和部署自定义控件来说是非常关键的步骤。理解并掌握这些知识,能够帮助IT专业人士更有效地管理和分发他们...
在制作OCX控件时,需要使用VS 2008创建一个新的工程,选择“MFC ActiveX控件”。在类视图中添加接口,注意接口的参数类型要与JS一致,数字型的参数用SHORT,字符串型的参数用BSTR。如果不一致,JS在调用接口时会提示...
本文将深入探讨如何利用InstallShield制作打包程序,并提供一段代码示例,帮助理解其工作原理。 首先,我们需要了解InstallShield的基本工作流程。创建一个InstallShield项目通常包括以下几个步骤: 1. **项目创建...
1. **CAB文件的制作**:CAB文件能够将多个文件打包成一个单一的下载单元,有助于减少网络传输的时间和带宽消耗。制作CAB文件通常需要用到专门的工具,如Microsoft的Makecab.exe或第三方的CAB压制工具。通过这些工具...
总之,myEclipse工程打包及exe文件制作是Java开发中的一个重要环节,通过合理利用各种工具,我们可以让Java应用程序更好地适应不同用户的需求。在实践中,不断学习和掌握这些技能,将有助于提升你的开发效率和软件...
总之,开发MFC ActiveX OCX控件并发布到.NET网站的过程涉及多个步骤,包括创建项目、添加功能、处理安全性、证书制作和签名,以及打包和发布。正确地执行这些步骤将确保控件能在Web环境中安全、顺畅地运行。在整个...
本程序是一款Windows平台下的软件安装包打包工具,目前版本主要具备如下功能: 1、支持多国语言安装界面 2、支持在安装过程中调用第三方安装程序 3、支持自动安装EXE服务和INF驱动 4、支持DLL和OCX 的安装和自动注册...
1. **建立安装程序**:使用第三方安装包制作工具,如Inno Setup或NSIS,创建一个包含控件`.dll`、`.tlb`和其他必要文件的安装程序。 2. **配置安装脚本**:在安装脚本中,添加注册控件的步骤,确保在用户计算机上...
7、除了多文件安装包外,还支持制作单一文件安装包,即所有的文件打包在一个setup.exe中 8、支持注册表、快捷栏、菜单栏、桌面图标、安装界面字体、大小、LOGO图片等的配置 本程序目前只能通过手工配置脚本的方式来...
7、除了多文件安装包外,还支持制作单一文件安装包,即所有的文件打包在一个setup.exe中 8、支持注册表、快捷栏、菜单栏、桌面图标、安装界面字体、大小、LOGO图片等的配置 本程序目前只能通过手工配置脚本的方式...
2. **CAB制作软件**:描述中提到的“CAB打包工具”可能是指Microsoft的Makecab工具,这是一个命令行实用程序,用于创建CAB文件。此外,还有其他第三方软件,如WinRAR或7-Zip,它们虽然不是专门用于制作CAB文件,但也...
- **步骤五**:如果应用程序依赖于第三方库(例如Codejock等),还需要将这些库的相关文件(如.ocx和.lic文件)拷贝到项目的文件夹下,并确保它们的注册设置正确。通常情况下,这些文件的注册设置默认为“不注册”,...
制作cab包的过程主要包括以下几个步骤: 1. **编写INF配置文件**: INF文件是cab包的核心,它包含了安装所需的所有信息。文件结构由不同的节组成,如`[Version]`、`[Add.Code]`等。`[Version]`节定义了文件适用的...
总结,InstallShield 2019作为一款强大的打包工具,不仅简化了软件部署过程,而且提供了丰富的定制选项,使得第三方OCX控件的集成变得轻松高效。熟练掌握InstallShield 2019的使用技巧,将大大提高开发者的生产力,...
3. **使用CAB打包工具**:使用Microsoft的Makecab工具或者第三方工具(如WiX工具集)创建CAB文件,指定INF文件作为配置。 4. **签名验证**:为了确保安全,可以对CAB文件进行数字签名,这样用户在安装时可以验证其...
- 在向导的第一个页面中,选择要包含在安装包中的文件和组件。 - 可以选择整个项目、特定的文件或文件夹等。 3. **指定安装后的卸载程序**: - 在后续页面中,可以指定卸载程序的路径,以便用户在不需要该应用...
Inno6,作为Inno Setup的第六个版本,是一款广泛应用于软件安装打包的工具,它以其便捷性和灵活性深受开发者喜爱。汉化inno6全中文界面的出现,更是为国内开发者提供了极大的便利,使得程序发布过程中的语言障碍得以...
1. "SysTray.ocx":这是一个ActiveX控件文件,通常用于VB环境中,提供拖放式的接口,使得开发者可以直接将控件添加到设计界面,然后通过编程来控制其行为,如添加托盘图标、响应右键菜单等。 2. "使用说明.txt":这...