解决控件只能在本地运行,不能在服务器上运行

默认情况下,编译的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;   

}

然后修改DllRegisterServerDllUnregisterServer这个两个方法做如下修改:

// 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_SafeForInitializingCATID_SafeForScripting在头文件Objsafe.h中,包含即可。

 

下一步,实现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&apos;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&apos;re always safe, this is a no-brainer--but we do check to make

// sure the interface requested exists and that the options we&apos;re asked to

// set exist and are set on (we don&apos;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&apos;t exist

              return ResultFromScode(E_NOINTERFACE);

       }

       // can&apos;t set bits we don&apos;t support

       if (dwOptionSetMask & dwNotSupportedBits) {

              return ResultFromScode(E_FAIL);

       }

 

       // can&apos;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&apos;t need to change anything since we&apos;re always safe

       return ResultFromScode(S_OK);

}

到此,ActiveX插件就可以注册为安全控件了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SQLite3 VB控件是一种可以通过Visual Basic编程语言来访问和管理SQLite3数据库的控件。SQLite是一款轻量级的嵌入式数据库引擎,而VB(Visual Basic)是一种广泛使用的编程语言。 使用SQLite3 VB控件,我们可以在VB应用程序中创建、读取、更新和删除SQLite3数据库中的数据。它提供了一些方法和属性,用于连接数据库、执行SQL查询语句以及处理返回的结果。 使用SQLite3 VB控件,我们可以进行一些基本的数据库操作,比如创建数据表、插入数据、更新数据和删除数据。我们还可以执行更复杂的查询,如条件查询、排序查询和联合查询等。通过SQLite3 VB控件,我们还可以处理数据库中的事务,从而确保数据的一致性和完整性。 SQLite3 VB控件还支持一些高级功能,如数据绑定和数据验证。我们可以将数据库中的数据绑定到VB控件上,比如列表框或数据网格控件,从而实现数据的显示和编辑。同时,我们也可以通过数据验证功能对用户输入的数据进行校验,以确保数据的有效性和安全性。 总之,SQLite3 VB控件是一种方便易用的工具,可以帮助我们在VB应用程序中操作SQLite3数据库。它提供了各种功能和方法,使得数据库操作变得简单和高效。无论是对于初学者还是有经验的开发人员来说,SQLite3 VB控件都是一个非常有用的工具。 ### 回答2: SQLite3 VB控件是一种用于在Visual Basic开发环境中连接和操作SQLite数据库的控件。SQLite是一种轻量级的嵌入式数据库引擎,它占用资源少且速度快,适用于小型应用的数据库存储需求。 使用SQLite3 VB控件可以在Visual Basic中直接连接SQLite数据库,并执行创建、查询、更新、删除等数据库操作。该控件提供了一系列的方法和属性来方便地操作SQLite数据库。例如,我们可以使用该控件提供的OpenDatabase方法来打开数据库连接,使用ExecuteSQL方法来执行SQL语句,使用GetRecordCount方法获取查询结果的记录数量等。 在使用SQLite3 VB控件时,我们需要先安装并引用该控件,然后在代码中创建该控件的实例,并设置相应的属性,如数据库路径、用户名、密码等。接着,就可以使用该控件的方法来执行数据库操作了。 使用SQLite3 VB控件有以下优点: 1. 简单易用:SQLite3 VB控件提供了直接的API和方法,使得在Visual Basic中连接和操作SQLite数据库变得简单和容易。 2. 快速高效:SQLite是一个独立的、高效的嵌入式数据库引擎,使用SQLite3 VB控件可以在Visual Basic应用程序中实现高性能的数据库操作。 3. 资源占用少:SQLite数据库引擎非常轻量级,占用的系统资源较少,适用于资源有限的环境或嵌入式系统。 4. 跨平台支持:SQLite数据库是跨平台的,可以在多种操作系统上运行,因此,可以将应用程序使用SQLite3 VB控件开发的代码无缝迁移到其他平台。 总结来说,SQLite3 VB控件是一种方便易用的Visual Basic控件,可以帮助开发者在应用程序中连接和操作SQLite数据库,实现高效、可靠的数据库存储和管理。 ### 回答3: SQLite3 VB控件是一种用于在Visual Basic (VB) 程序中连接和操作SQLite3数据库的控件。SQLite是一种轻量级的嵌入式数据库引擎,通过SQLite3 VB控件,我们可以在VB程序中运用SQLite数据库的功能。 使用SQLite3 VB控件,我们可以轻松地在VB程序中创建、打开和关闭SQLite3数据库。我们可以执行SQL语句来创建表格,插入、更新和删除数据,以及查询和检索数据。SQLite3 VB控件提供了简单易用的API,让我们能够以编程的方式控制数据库的操作。 SQLite3 VB控件还提供了对事务的支持,这允许我们在执行多个操作时保持数据的一致性。我们可以通过启动事务,执行多个操作,然后提交或回滚事务来确保数据的完整性。 SQLite3 VB控件还具有优秀的性能和效率。SQLite是一个单个文件的数据库引擎,不需要额外的服务器配置,因此它非常适合需要在本地存储数据的小型项目。与其他数据库引擎相比,SQLite3 VB控件在处理大量数据时表现出色,并且消耗的系统资源较少。 总之,SQLite3 VB控件是一种方便且易于使用的工具,使得我们能够在VB程序中轻松地连接和操作SQLite3数据库。无论是创建、插入、更新、删除数据,还是查询和检索数据,SQLite3 VB控件都为我们提供了简单而强大的API。如果需要在VB程序中使用SQLite数据库,SQLite3 VB控件是一个很好的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值