使你的ActiveX控件执行时不弹出安全性提示 您所在的位置:网站首页 网页不弹出运行控件 使你的ActiveX控件执行时不弹出安全性提示

使你的ActiveX控件执行时不弹出安全性提示

2024-04-11 08:22| 来源: 网络整理| 查看: 265



一个很好的总结文章帖

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

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

必须包括两个头文件

#include #include

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 > 127) {    len = 127; }     lstrcpyn((TCHAR*)(catinfo.szDescription), catDescription, len+1);     hr = pcr->RegisterCategories(1, &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(1, &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[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; }

//使你的控件不弹出警告地执行 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 #include //增加这个头文件

// 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》。

http://blog.csdn.net/zhyt_213/article/details/6597303



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有