我们编写一个ActiveX控件在IE中运行,一般会弹出一个安全提示,如何避免这种情况?下面是我在参考前人的文章后,总结出“在浏览器中执行时不弹出警告的ActiveX控件”的两种编写方法,予以备忘。注意,这里不会弹出警告是说在执行时不会弹出,也就是说已经安装了这个ActiveX控件。如果要下载安装这个ActiveX控件时不会弹出安全警告,恐怕就得去买数字证书了。不过即使有数字证书,还是得用户同意后才会下载安装。
以下两种方法在WINXP-SP2+VC6下通过。

方法1:修改注册表 可能你在看完下面的过程后会发现,程序没有一个地方对注册表操作过。其实不然,这里所谓的修改注册表的方法就是使用组件类型管理器(Component Categories Manager)创建一个正确的入口到系统注册表。IE通过检测注册表判断一个控件是否可以安全地初始化和脚本操作。IE会通过调用 ICatInformation::IsClassOfCategories 方法确定控件是否支持给出的安全性分组。其中对注册表的操作都已经封装起来,隐藏在底层了,所以看不到。

必须包括两个头文件

#include <comcat.h>
#include <Objsafe.h> const GUID CDECL CLSID_SafeItem =
{0xD321B11E, 0x8E79, 0x4829, 0xAB, 0x80, 0x9E, 0x59, 0x92, 0x06, 0xAB, 0xB7};//用你的控件类GUID替换
// 注册组件种类为安全
HRESULT AddCategorySafty(CATID catid, TCHAR* 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; CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = 0x0409 ; // 英语语言 // 最长只拷贝127个字符。
int len = lstrlen(catDescription);
if (len > )
{
len = ;
}
lstrcpyn((TCHAR*)(catinfo.szDescription), catDescription, len+); hr = pcr->RegisterCategories(, &catinfo);
pcr->Release(); return hr;
} //移除已经注册为安全的组件种类
HRESULT RemoveCategorySafty(CATID catid)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ; hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr; hr = pcr->UnRegisterCategories(, &catid);
pcr->Release(); return hr;
} // 把你的控件注册到已经注册为安全的组件种类
HRESULT RegisterCLSIDInCategory(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))
{
CATID rgcatid[] ;
rgcatid[] = catid;
hr = pcr->RegisterClassImplCategories(clsid, , 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[] ;
rgcatid[] = catid;
hr = pcr->UnRegisterClassImplCategories(clsid, , rgcatid);
} if (pcr != NULL)
pcr->Release(); return hr;
} //使你的控件不弹出警告地执行
HRESULT MakeActiveXSafty(REFCLSID clsid)
{
HRESULT hr; hr = AddCategorySafty(CATID_SafeForInitializing,
_T("Controls safely initializable!"));
if (FAILED(hr))
return hr;
hr = RegisterCLSIDInCategory(clsid, CATID_SafeForInitializing);
if (FAILED(hr))
return hr; hr = AddCategorySafty(CATID_SafeForScripting, _T("Controls safely scriptable!"));
if (FAILED(hr))
return hr;
hr = RegisterCLSIDInCategory(clsid, CATID_SafeForScripting); return hr;
} //去除控件的安全执行性
HRESULT UnMakeActiveXSafty(REFCLSID clsid)
{
HRESULT hr;
hr = UnRegisterCLSIDInCategory(clsid, CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
hr = UnRegisterCLSIDInCategory(clsid, CATID_SafeForScripting);
if (FAILED(hr))
return hr; //下面的代码是把安全组件种类去掉。去掉的话,如果有其他的控件注册为这两个种类
//那么其他的控件执行时就会弹出警告。需不需要下面的代码就见仁见智,看实际情况了
hr = RemoveCategorySafty(CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
hr = RemoveCategorySafty(CATID_SafeForScripting); return hr;
}

然后在DllRegisterServer函数的“return NOERROR;”前添加如下代码:

HRESULT hr = MakeActiveXSafty(CLSID_SafeItem);
if (FAILED(hr))
return hr;

在DllUnregisterServer函数的“AFX_MANAGE_STATE(_afxModuleAddrThis);”后添加如下代码:

HRESULT hr = UnMakeActiveXSafty(CLSID_SafeItem);
if (FAILED(hr))
OutputDebugString(_T("去除控件的安全执行性时出错!"));

方法2:实现ObjectSafe接口

我创建了一个MFC ActiveX ControlWizard的工程,工程为TestAX,它的控件类是CTestAXCtrl,下面所有的代码和操作都是在这个类的头文件和实现文件中进行。红色的部分是为了实现ObjectSafe接口而增加的代码。

在头文件中:

#if !defined(AFX_TESTAXCTL_H__C2084528_F93E_42D8_A13D_7E38775A0481__INCLUDED_)
#define AFX_TESTAXCTL_H__C2084528_F93E_42D8_A13D_7E38775A0481__INCLUDED_ #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 // #include <ComCat.h>
#include <ObjSafe.h>//增加这个头文件 // TestAXCtl.h : Declaration of the CTestAXCtrl ActiveX Control class. /////////////////////////////////////////////////////////////////////////////
// CTestAXCtrl : See TestAXCtl.cpp for implementation. class CTestAXCtrl : public COleControl
{
DECLARE_DYNCREATE(CTestAXCtrl) // Constructor
public:
CTestAXCtrl(); //增加如下代码:
DECLARE_INTERFACE_MAP() BEGIN_INTERFACE_PART(MyObjSafe, 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(MyObjSafe); 。。。。。。 在实现文件中: // TestAXCtl.cpp : Implementation of the CTestAXCtrl ActiveX Control class. #include "stdafx.h"
#include "testAX.h"
#include "TestAXCtl.h"
#include "TestAXPpg.h" #ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif IMPLEMENT_DYNCREATE(CTestAXCtrl, COleControl) //接口映射
BEGIN_INTERFACE_MAP(CTestAXCtrl, COleControl )
INTERFACE_PART(CTestAXCtrl, IID_IObjectSafety, MyObjSafe)
END_INTERFACE_MAP() 。。。。。。(其他代码省略) //接口的函数实现
ULONG FAR EXPORT CTestAXCtrl::XMyObjSafe::AddRef()
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
return pThis->ExternalAddRef();
} ULONG FAR EXPORT CTestAXCtrl::XMyObjSafe::Release()
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
return pThis->ExternalRelease();
} HRESULT FAR EXPORT CTestAXCtrl::XMyObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
} //调用方法与数据是否可信任,设置这两个标志位就可以了
const DWORD g_dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD g_dwNotSupportedBits = ~g_dwSupportedBits; HRESULT FAR EXPORT CTestAXCtrl::XMyObjSafe::GetInterfaceSafetyOptions(REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions)
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
*pdwSupportedOptions = *pdwEnabledOptions = g_dwSupportedBits;
return S_OK;
} HRESULT FAR EXPORT CTestAXCtrl::XMyObjSafe::SetInterfaceSafetyOptions(REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions)
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe) //如果有任何一个不支持的设置位,则返回不支持错误。
if (dwOptionSetMask & g_dwNotSupportedBits)
{
return CO_E_NOT_SUPPORTED;
}
//不需要做其他的事情
return S_OK;
}

详细的接口实现步骤请参考MSDN的《TN038: MFC/OLE IUnknown Implementation》。

原文链接

使你的ActiveX控件执行时不弹出安全性提示(转载)的更多相关文章

  1. 已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决

    已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决   情况一:当该控件未注册或者已经卸载时,你尝试卸 ...

  2. 配置Info.plist (设置状态栏样式、自定义定位时系统弹出的提示语、配置3DTouch应用快捷菜单)

    一.概述 iOS中很多功能需要配置Info.plist才能实现,如设置后台运行.支持打开的文件类型.自定义访问隐私内容时弹出的提示等.了解Info.plist中各字段及其含义,可以访问苹果开发网站相关 ...

  3. android中RecyclerView控件实现长按弹出PopupMenu菜单功能

    之前写过一篇文章:android中实现简单的聊天功能 现在是在之前功能的基础上,添加一个长按聊天记录,删除对应聊天记录的功能 RecyclerView控件,没有对应的长按事件,我们需要自己手工添加,修 ...

  4. 自己写个activex控件,如何知道他的classid(转载)

    在网页里用的时候需要知道他的classid我在代码中看到有 const GUID CDECL BASED_CODE _tlid = { 0x89201950, 0x2CAC, 0x4CF7, { 0x ...

  5. VC6.0 MFC中WebBrowser控件禁止新窗口弹出的解决办法

    http://blog.csdn.net/gnorth/article/details/7258293 分类: WebBrowser MFC 禁止新窗口2012-02-14 15:25 1787人阅读 ...

  6. VB动态添加WebBrowser控件,并拦截弹出窗口(不用引用任何组件)

    新建空白窗体,然后粘帖下面代码: Option ExplicitPublic WithEvents br As VBControlExtender Private Sub br_ObjectEvent ...

  7. jqgrid 获取远端数据失败时,弹出错误提示

    有时,我们给jqgrid绑定的远端数据获取失败,此时,需要把错误信息反馈给用户展示,如何实现? 可通过jqgrid的 loadError 来处理错误数据的返回.详细如下: $("#jqGri ...

  8. Xcode调试项目时取消弹出框提示授权

    问题2: instruments wants permission to analyze other processes.'DTServiceHub'需要控制另外一个进程,以便继续调试,键入密码以允许 ...

  9. 解决IE打开时,弹出的提示调用active的问题,阻止js运行。

    在html和head中间加上: <!-- saved from url=(0014)about:internet -->

随机推荐

  1. Chrome 声音自动播放抱错问题【play() failed】

    Chrome下调用play后抱错:DOMException: play() failed because the user didn't interact with the document firs ...

  2. 动态赋值poster,无法显示

    vue操作video的poster属性时,动态给poster赋值,在chrome下是无法显示的 解决办法 在赋值后,找到video元素.load()下就会看到封面图了

  3. webpack 启动 vue

    右击 package.json  单击show npm Scripts

  4. Redhat Linux 7.3 虚拟机通过USB挂载NTFS格式的移动硬盘

    分为如下几个步骤: 一.设置本地yum,安装gcc(如果本机已经安装gcc,则跳过此步) 在虚拟机连接linux iso安装盘 查看光盘挂载情况 mkdir /iso mount /dev/cdrom ...

  5. RC4 加解密

    加密解密都是这一个接口 int Rc4EncryptFile(std::string in_file_path, std::string out_file_path, const char *rc4_ ...

  6. C语言数组指针(指向数组的指针)

    注意:数组指针的定义,与指针数组的区别 转载:http://c.biancheng.net/cpp/biancheng/view/162.html 指向多维数组元素的指针变量 ① 指向数组元素的指针变 ...

  7. arm汇编学习(三)

    一.ndk编译android上运行的c程序 新建个hello目录,底下要有jni目录,下面就是Android.mk文件 1.Android.mk文件内容如下: LOCAL_PATH:= $(call ...

  8. vs2013 c# 中调用 c 编写的dll出错的可能错误

    先说出错原因:    堆栈调用顺序  解决办法:     使用   __stdcall 或 使用C#属性 CallingConvention 起因是我想在c#中调用c函数结果出错了 如下 C 头文件 ...

  9. Apache2.4和IIS7整合共享80端口测试

    言我再重新排版一下 在C:\Windows\System32\drivers\etc\hosts文件中配置2个测试域名用于整合测试 127.0.0.1 www.aaa.com // apache项目 ...

  10. 【Leetcode】【Medium】Binary Tree Right Side View

    Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...