MFC ActiveX开发基础2:ActiveX控件在Internet上发布
来源:互联网 发布:最全私人网络理财投资 编辑:程序博客网 时间:2024/06/05 09:16
开发完ActiveX控件后,对于发布也有许多麻烦,稍微不小心你的ActiveX便变成一个红叉,以下所介绍的每一点都不可或缺,经过这几点后ActiveX控件将顺利的显示在Internet 网页中,这时候可以看到win7中C:\Windows\Downloaded Program Files目录中有你所发布的Activex文件,并可在浏览器的加载项中找到已加载的ActiveX控件:
1.ActiveX的发布首先当然需要一个ActiveX控件,通过MFC ActiveX基础1:http://blog.csdn.net/acsder2010413/article/details/26385535生成DemoActiveX.ocx
2.将ActiveX控件放在网页中,以下代码为html使用ActiveX示例
<html><body><object classid="clsid:826CAAE8-CEAC-4317-BAC7-60BF39279C4F" codebase="UpgradeController.ocx#version=1,0,0,1" width="600" height="500"></object></body></html>html使用Object标签来支持各种插件,对于html object支持的插件情况可见:http://www.w3school.com.cn/html/html_object.asp
Object标签可以支持向Html中插入Activex控件,这里用到两个主要属性:
a. classid
classidclass ID定义嵌入 Windows Registry 中或某个 URL 中的类的 ID 值,此属性可用来指定浏览器中包含的对象的位置,通常是一个 Java 类。b.codebasecodebaseURL定义在何处可找到对象所需的代码,提供一个基准 URL。上述html例子中将网页与ActiveX控件放到同一目录下,所以codebase属性可以不设路径。大家应该发现这个codebase设置的属性中文件路径名后还带有“#version1.0.0.1”,version实际是用来指定要发布的Activex的版本号,该版本号需要与ocx文件的版本号(文件属性->详细信息中查看)对应上,用来告诉浏览器是否要更新本地的ActiveX控件,当#version中指定的版本号大于本地文件版本时浏览器便会提示用户进行Activex的更新,新的ocx文件将被更新到C:\Windows\Downloaded Program Files\CONFLICT.n系列文件夹中
对于Object标签详见:http://www.w3school.com.cn/tags/tag_object.asp
3. 为ActiveX控件添加IObjectSafty接口,使得ActiveX被注册为安全控件,并且顺利的通过Internet Explorer的安全检查(经验证可通过默认安全级别(中-高级别))
未添加IObjectSafty接口的ActiveX控件,将不能通过Internet Explorer的默认安全级别(Internet选项-》安全),需要通过降低安全级别并启用有关ActiveX控件的安全选项,这里稍微设置不好就可能使ActiveX控件无法使用,故显然添加IObjectSafty接口顺利通过安全级别才是最佳选择。
对于IObjectSafty接口与ActiveX控件可见:http://blog.csdn.net/optman/article/details/1698070
那么如何实现IObjectSafty接口
以下IObjectSafty接口实现经验证可行,引自:http://jiangsy1107.blog.sohu.com/201048568.html
默认情况下,编译的MFC Activex控件,只能在本地代码中运行,要想放在服务器通过IE远程访问,需要设置其初始化和脚本运行的安全性,做以下修改:
在“工程名.cpp”文件中,增加以下方法:
// 创建组件种类
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_s(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;
}
然后修改DllRegisterServer和DllUnregisterServer这个两个方法做如下修改:
// DllRegisterServer - 将项添加到系统注册表
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 - 将项从系统注册表中移除
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;
}
其中CATID_SafeForInitializing和CATID_SafeForScripting两个是guid,可以通过VC自带的guid生成工具自动生成。
下一步,实现IobjectSafety接口,步骤:
打开 “工程名Ctrl.h”
加入#include<objsafe.h>,
搜索
DECLARE_DYNCREATE(C工程名Ctrl)
在其下面添加:
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)
STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (
REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions
);
STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions
);
END_INTERFACE_PART(ObjSafe);
打开“工程名Ctl.cpp”
在
BOOL C工程名Ctrl::C工程名CtrlFactory::UpdateRegistry(BOOL bRegister)
方法上面添加以下代码:
/////////////////////////////////////////////////////////////////////////////
// Interface map for IObjectSafety
BEGIN_INTERFACE_MAP(C工程名Ctrl, COleControl)
INTERFACE_PART(C工程名Ctrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// IObjectSafety member functions
// Delegate AddRef, Release, QueryInterface
ULONG FAR EXPORT C工程名Ctrl::XObjSafe::AddRef()
{
METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT C工程名Ctrl::XObjSafe::Release()
{
METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT C工程名Ctrl::XObjSafe::QueryInterface(
REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
const DWORD dwSupportedBits =
INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD dwNotSupportedBits = ~ dwSupportedBits;
/////////////////////////////////////////////////////////////////////////////
// CStopLiteCtrl::XObjSafe::GetInterfaceSafetyOptions
// Allows container to query what interfaces are safe for what. We're
// optimizing significantly by ignoring which interface the caller is
// asking for.
HRESULT STDMETHODCALLTYPE
C工程名Ctrl::XObjSafe::GetInterfaceSafetyOptions(
REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions)
{
METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)
HRESULT retval = ResultFromScode(S_OK);
// does interface exist?
IUnknown FAR* punkInterface;
retval = pThis->ExternalQueryInterface(&riid,
(void * *)&punkInterface);
if (retval != E_NOINTERFACE) { // interface exists
punkInterface->Release(); // release it--just checking!
}
// we support both kinds of safety and have always both set,
// regardless of interface
*pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;
return retval; // E_NOINTERFACE if QI failed
}
/////////////////////////////////////////////////////////////////////////////
// CStopLiteCtrl::XObjSafe::SetInterfaceSafetyOptions
// Since we're always safe, this is a no-brainer--but we do check to make
// sure the interface requested exists and that the options we're asked to
// set exist and are set on (we don't support unsafe mode).
HRESULT STDMETHODCALLTYPE
C工程名Ctrl::XObjSafe::SetInterfaceSafetyOptions(
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions)
{
METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)
// does interface exist?
IUnknown FAR* punkInterface;
pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
if (punkInterface) { // interface exists
punkInterface->Release(); // release it--just checking!
}
else { // interface doesn't exist
return ResultFromScode(E_NOINTERFACE);
}
// can't set bits we don't support
if (dwOptionSetMask & dwNotSupportedBits) {
return ResultFromScode(E_FAIL);
}
// can't set bits we do support to zero
dwEnabledOptions &= dwSupportedBits;
// (we already know there are no extra bits in mask )
if ((dwOptionSetMask & dwEnabledOptions) !=
dwOptionSetMask) {
return ResultFromScode(E_FAIL);
}
// don't need to change anything since we're always safe
return ResultFromScode(S_OK);
}
到此,ActiveX插件就可以注册为安全控件了。
另:网上有介绍将ActiveX打包成cab并添加签名来发布,可通过Internet Explorer的安全检验,但经过试验没有成功。
- MFC ActiveX开发基础2:ActiveX控件在Internet上发布
- 如何在Internet上发布Activex控件(VB)
- MFC Activex控件开发
- Internet上用ActiveX发布软件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- 使用MFC开发ActiveX控件
- VC2005开发MFC ActiveX控件
- 使用MFC开发ActiveX控件
- ActiveX 控件与Internet
- ActiveX 控件与Internet
- coco2dx客户端聊天系统(普通版)
- javascript中的null,空串和undefined
- EditText光标默认在第一行,edittext不显示键盘 ,edittext失去焦点
- Android之菜单总结
- cocos2dx3.2 由Hello_World看整体思路
- MFC ActiveX开发基础2:ActiveX控件在Internet上发布
- Apache Tomcat 8 WebSocket How-To 中文翻译版
- struts 拦截器设置防止表单的重复提交
- VC6.0创建hello-World程序
- Binary search
- android 4.4 设置默认短信 和来电短信拒接
- 如何重定向cin和cout?
- leetcode Single Number II
- PHP入门基础系列教程(价值499元)