visual studio 2013 快速安全ocx(ActiveX控件)开发

OCX 专栏收录该内容
13 篇文章 1 订阅

1.打开visual studio 2013

2.新建ocx项目: 文件–>新建–>项目–>visual C++ –>MFC –>MFC ActiveX控件–>确定 –>完成

3.快速添加对外开放的方法和属性:切换到类视图–>选中HelloWorldLib下_DHelloWorld右击–>添加–> 添加方法

4.设置不需要MSVCP120*.dll支持 ,解决oxc放到其他电脑上注册不需要MSVCP120*.dll :项目名称右击–>属性 –>(活动debug)(RElease)—>常规 –>MFC 的使用 –>在静态库中使用MFC

5.将ocx设置为安全的(IE调用时不会弹窗提示).对XXX.cpp(项目名.cpp)进行修改 
参考和引用该博文http://blog.csdn.net/waxgourd0/article/details/7411620

(1)添加头文件

#include "ComCat.h"
#include "strsafe.h"
#include "ObjSafe.h"

(2)添加 CLSID_SafeItem 值与XXXCtrl.cpp 文件中IMPLEMENT_OLECREATE_EX 的值一致

const GUID CDECL CLSID_SafeItem =
{ 0x1535c313, 0xcbb8, 0x4e88, 0x84, 0x40, 0xe7, 0x8d, 0xa1, 0x68, 0x4c, 0x3f };

(3)添加3个方法

//创建Component Categories中的初始化安全和脚本安全项
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;

    // 确认HKCR\Component Categories\{..catid...}键值被注册
    CATEGORYINFO catinfo;
    catinfo.catid = catid;
    catinfo.lcid = 0x0409; // english
    //size_t len;
    // 确认描述不是太长。
    // 只复制开始的127个字符。
    // StringCchLength的第二个参数表示被读入catDescription的最大字符数。
    // 第三个参数表示字符串的长度
    //hr = StringCchLength(catDescription, STRSAFE_MAX_CCH, &len);
    int len = wcslen(catDescription);
    if (SUCCEEDED(hr))
    {
        if (len>127)
        {
            len = 127;
        }
    }
    else
    {
        // TODO: Write an error handler;
    }

    wcsncpy(catinfo.szDescription, catDescription, len);
    //hr = StringCchCopy(catinfo.szDescription, len + 1, catDescription);
    // 添加字符串结束符.
    //catinfo.szDescription[len + 1] = '\0';
    catinfo.szDescription[len] = '/0';

    hr = pcr->RegisterCategories(1, &catinfo);
    pcr->Release();
    return hr;
}

//在CLSID中创建与Component Categories中初始化安全和脚本安全项中相对应的implemented Categories项
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;

}

//注销与CLSID中的相应implemented Categories项,一般用不到,因为其它程序可能也会用到这此项
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))
    {
        CATID rgcatid[1];
        rgcatid[0] = catid;
        hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
    }

    if (pcr != NULL)
        pcr->Release();
    return hr;
}

(4) 在 DllRegisterServer()方法中添加代码块

  //创建脚本安全“补充”项,非CLSID中
    HRESULT hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
    if (FAILED(hr))
        return hr;

    //创建初始化安全“补充”项,非CLSID中
    hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");
    if (FAILED(hr))
        return hr;

    //设置控件CLSID中补充项的脚本安全项,与“补充”项中的脚本安全项对应
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

    //设置控件CLSID中补充项的初始化安全项,与“补充”项中的初始化安全项对应
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;

 (5) 在 DllUnregisterServer()方法中添加代码块

// 删除控件初始化安全入口.
    HRESULT hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;

    // 删除控件脚本安全入口
    hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

参考HelloWorld.cpp

// helloWorld.cpp : ChelloWorldApp 和 DLL 注册的实现。

#include "stdafx.h"
#include "helloWorld.h"
#include "ComCat.h"
#include "strsafe.h"
#include "ObjSafe.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


ChelloWorldApp theApp;

const GUID CDECL  _tlid = { 0x231918E0, 0xB0A6, 0x4F27, { 0x82, 0xC8, 0xAE, 0xB7, 0x9C, 0x1D, 0x2B, 0xE } };
const GUID CDECL CLSID_SafeItem =
{ 0x1535c313, 0xcbb8, 0x4e88, 0x84, 0x40, 0xe7, 0x8d, 0xa1, 0x68, 0x4c, 0x3f };
const WORD _wVerMajor = 1;
const WORD _wVerMinor = 0;



// ChelloWorldApp::InitInstance - DLL 初始化

BOOL ChelloWorldApp::InitInstance()
{
    BOOL bInit = COleControlModule::InitInstance();

    if (bInit)
    {
        // TODO:  在此添加您自己的模块初始化代码。
    }

    return bInit;
}



// ChelloWorldApp::ExitInstance - DLL 终止

int ChelloWorldApp::ExitInstance()
{
    // TODO:  在此添加您自己的模块终止代码。

    return COleControlModule::ExitInstance();
}


//创建Component Categories中的初始化安全和脚本安全项
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;

    // 确认HKCR\Component Categories\{..catid...}键值被注册
    CATEGORYINFO catinfo;
    catinfo.catid = catid;
    catinfo.lcid = 0x0409; // english
    //size_t len;
    // 确认描述不是太长。
    // 只复制开始的127个字符。
    // StringCchLength的第二个参数表示被读入catDescription的最大字符数。
    // 第三个参数表示字符串的长度
    //hr = StringCchLength(catDescription, STRSAFE_MAX_CCH, &len);
    int len = wcslen(catDescription);
    if (SUCCEEDED(hr))
    {
        if (len>127)
        {
            len = 127;
        }
    }
    else
    {
        // TODO: Write an error handler;
    }

    wcsncpy(catinfo.szDescription, catDescription, len);
    //hr = StringCchCopy(catinfo.szDescription, len + 1, catDescription);
    // 添加字符串结束符.
    //catinfo.szDescription[len + 1] = '\0';
    catinfo.szDescription[len] = '/0';

    hr = pcr->RegisterCategories(1, &catinfo);
    pcr->Release();
    return hr;
}

//在CLSID中创建与Component Categories中初始化安全和脚本安全项中相对应的implemented Categories项
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;

}

//注销与CLSID中的相应implemented Categories项,一般用不到,因为其它程序可能也会用到这此项
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))
    {
        CATID rgcatid[1];
        rgcatid[0] = catid;
        hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
    }

    if (pcr != NULL)
        pcr->Release();
    return hr;
}





// DllRegisterServer - 将项添加到系统注册表

STDAPI DllRegisterServer(void)
{
    AFX_MANAGE_STATE(_afxModuleAddrThis);

    if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
        return ResultFromScode(SELFREG_E_TYPELIB);

    if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
        return ResultFromScode(SELFREG_E_CLASS);

    //创建脚本安全“补充”项,非CLSID中
    HRESULT hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
    if (FAILED(hr))
        return hr;

    //创建初始化安全“补充”项,非CLSID中
    hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");
    if (FAILED(hr))
        return hr;

    //设置控件CLSID中补充项的脚本安全项,与“补充”项中的脚本安全项对应
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

    //设置控件CLSID中补充项的初始化安全项,与“补充”项中的初始化安全项对应
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;

    return NOERROR;
}



// DllUnregisterServer - 将项从系统注册表中移除

STDAPI DllUnregisterServer(void)
{
    AFX_MANAGE_STATE(_afxModuleAddrThis);

    if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
        return ResultFromScode(SELFREG_E_TYPELIB);

    if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
        return ResultFromScode(SELFREG_E_CLASS);

    // 删除控件初始化安全入口.
    HRESULT hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))
        return hr;

    // 删除控件脚本安全入口
    hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))
        return hr;

    return NOERROR;
}

6.当日要是不考虑安全的oxc(IE调用时不弹提示窗),可以忽略步骤5。。对HelloWorld.cpp进行编译–>生成–>测试

编译和生产中出现该错误的解决方案参考http://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html 

添加:_CRT_SECURE_NO_WARNINGS 

遇到这种情况。首先查看属性页面(右击项目名称点击”属性“)中–>链接器–>逐用户重定向 ==否

 

然后关闭visual Studio 2013 在以管理员的身份运行visual Studio 2013后再打开项目(点击文件–>打开–>项目/解决方案–>打开该项目文件夹–>选中 .sln 文件打开) 最后再次 点击生成–>生成

以管理员的身份注册

HelloWorld.html 其中classid 为HelloWord.idl 中的 的类信息中的uuid

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>ActiveX测试</title>

<script language = 'javascript'>
         function onObjectError(){       
            alert("error");
         }
</script>
<OBJECT id="MYAvtiveX" onerror="onObjectError();" style="width:0px;height:0" classid="CLSID:1535C313-CBB8-4E88-8440-E78DA1684C3F" > </OBJECT>
</head>

 <script language = 'javascript'>
         function AddFun(){
           var iResult = MYAvtiveX.HelloWorld();//调用ActiveX控件的AddFun方法。
           alert(iResult);
         }

</script>

<body>

<fieldset>

<legend>MyActiveX测试</legend>

    <table width="100%" border="1">

      <tr>

        <td width="20%"><input type='button' onclick='AddFun()' value='AddFun'> </td>

      </tr>   

    </table>

</fieldset>

</body>

</html>

 

 

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值