MFC写的ActiveX控件,在Javascript里面调用,但在IE总是有警告框:“An ActiveX control on this page might be unsafe to interact with other parts of the page. Do you want to allow this interaction?”这里的方法http://support.microsoft.com/kb/161873/, 试过,但还是不行,不知道什么原因。请大家帮忙!
解决方案 »
- GetDocument();离奇问题
- ModifyStyle能修改控件的全部风格吗,如果不能:那哪些不能,为什么
- CreateProcessWithLogonW -> RunAs或Secondary Logon时,用户名被修改的问题
- 请教如何实现屏蔽Edit Box 的 CTRL 键输入? 在线等。。。
- runtime error R6025 - pure virtual function call 错误!急!请帮忙解决!
- 讨论怎样看候捷的《深入浅出MFC》,和大家看这本书的感想,看这本书所遇到的困难和经历,大家说清楚一点呀!小弟我愿意拿出100分献给大哥
- 发放个查看exe文件的小工具,增加人气...
- 【求助】关于CListCtrl可变报表表头的设计方法~
- 在VC中自定义了窗口,怎样保存下来?以便重装系统后在VC中能恢复我的自定义工具栏?
- GetDlgItem要求调用的dialogbox的handle值,如何取得?
- 救命!求有关cppunit方面的资料
- 屏幕取词
总述
本文叙述了如何在VB中实现控件的IobjectSafety接口,以标志该控件是脚本安全和初始化安全的。VB控件默认的处理方式是在注册表中注册组件类来标识其安全性,但实现IobjectSafety接口是更好的方法。本言语包括了实现过程中所需的所有代码。 请注意,控件只有确确实实是安全的,才能被标识为“安全的”。本文并未论及如何确保控件的安全性,这个问题请参阅Internet Client Software Development Kit (SDK)中的相关文档 "Safe Initialization and Scripting for ActiveX Controls",它在Component Development 栏目中。 相关信息:
<此处略去了一段也许无关紧要的警告>现在开始循序渐进地举例说明怎样创建一个简单的VB控件,以及怎样将它标识为脚本安全和初始化安全。
首先新建一个文件夹来存放在本例中所产生的文件。从VB CD-ROM取得OLE 自动化类库的制作工具。将VB安装光盘中\Common\Tools\VB\Unsupprt\Typlib\目录下所有内容一并拷贝到前面新建的项目文件夹中。
把下列内容拷贝到“记事本”中,然后保存到上述文件夹,文件名为Objsafe.odl:
[
uuid(C67830E0-D11D-11cf-BD80-00AA00575603),
helpstring("VB IObjectSafety Interface"),
version(1.0)
]
library IObjectSafetyTLB
{
importlib("stdole2.tlb");
[
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
helpstring("IObjectSafety Interface"),
odl
]
interface IObjectSafety:IUnknown {
[helpstring("GetInterfaceSafetyOptions")]
HRESULT GetInterfaceSafetyOptions(
[in] long riid,
[in] long *pdwSupportedOptions,
[in] long *pdwEnabledOptions); [helpstring("SetInterfaceSafetyOptions")]
HRESULT SetInterfaceSafetyOptions(
[in] long riid,
[in] long dwOptionsSetMask,
[in] long dwEnabledOptions);
}
}
在命令行提示符下切换到项目文件夹,输入下列命令创建一个.tlb 文件:
MKTYPLIB objsafe.odl /tlb objsafe.tlb
在VB中新建一个ActiveX Control 项目。修改属性,把项目命名为IobjSafety,控件命名为DemoCtl。在控件上放置一个按钮,命名为cmdTest,在它的Click事件中加入一句代码 MsgBox "Test" 。
打开菜单“工程->引用”,点“浏览”,找到刚刚建立的Objsafe.tlb,把它加入到引用中。
增加一个新module名为basSafeCtl,并在其中加入下列代码:
Option Explicit Public Const IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"
Public Const IID_IPersistStorage = _
"{0000010A-0000-0000-C000-000000000046}"
Public Const IID_IPersistStream = _
"{00000109-0000-0000-C000-000000000046}"
Public Const IID_IPersistPropertyBag = _
"{37D84F60-42CB-11CE-8135-00AA004BB851}" Public Const INTERFACESAFE_FOR_UNTRUSTED_CALLER = &H1
Public Const INTERFACESAFE_FOR_UNTRUSTED_DATA = &H2
Public Const E_NOINTERFACE = &H80004002
Public Const E_FAIL = &H80004005
Public Const MAX_GUIDLEN = 40 Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDest As Any, pSource As Any, ByVal ByteLen As Long)
Public Declare Function StringFromGUID2 Lib "ole32.dll" (rguid As _
Any, ByVal lpstrClsId As Long, ByVal cbMax As Integer) As Long Public Type udtGUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type Public m_fSafeForScripting As Boolean
Public m_fSafeForInitializing As Boolean Sub Main()
m_fSafeForScripting = True
m_fSafeForInitializing = True
End Sub
在工程属性中把启动对象改成Sub Main确保上述代码会被执行。m_fSafeForScripting 和m_fSafeForInitializing两件变量的值分别指定了脚本安全和初始化安全取值。
打开控件代码窗口,在声明部分加入如下代码(如果有Option Explicit语句,当然要保证代码放在其后):
Implements IObjectSafety
把下面两个过程代码拷贝到控件代码中:
Private Sub IObjectSafety_GetInterfaceSafetyOptions(ByVal riid As _
Long, pdwSupportedOptions As Long, pdwEnabledOptions As Long) Dim Rc As Long
Dim rClsId As udtGUID
Dim IID As String
Dim bIID() As Byte pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER Or _
INTERFACESAFE_FOR_UNTRUSTED_DATA If (riid <> 0) Then
CopyMemory rClsId, ByVal riid, Len(rClsId) bIID = String$(MAX_GUIDLEN, 0)
Rc = StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)
Rc = InStr(1, bIID, vbNullChar) - 1
IID = Left$(UCase(bIID), Rc) Select Case IID
Case IID_IDispatch
pdwEnabledOptions = IIf(m_fSafeForScripting, _
INTERFACESAFE_FOR_UNTRUSTED_CALLER, 0)
Exit Sub
Case IID_IPersistStorage, IID_IPersistStream, _
IID_IPersistPropertyBag
pdwEnabledOptions = IIf(m_fSafeForInitializing, _
INTERFACESAFE_FOR_UNTRUSTED_DATA, 0)
Exit Sub
Case Else
Err.Raise E_NOINTERFACE
Exit Sub
End Select
End If
End Sub Private Sub IObjectSafety_SetInterfaceSafetyOptions(ByVal riid As _
Long, ByVal dwOptionsSetMask As Long, ByVal dwEnabledOptions As Long)
Dim Rc As Long
Dim rClsId As udtGUID
Dim IID As String
Dim bIID() As Byte If (riid <> 0) Then
CopyMemory rClsId, ByVal riid, Len(rClsId) bIID = String$(MAX_GUIDLEN, 0)
Rc = StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)
Rc = InStr(1, bIID, vbNullChar) - 1
IID = Left$(UCase(bIID), Rc) Select Case IID
Case IID_IDispatch
If ((dwEnabledOptions And dwOptionsSetMask) <> _
INTERFACESAFE_FOR_UNTRUSTED_CALLER) Then
Err.Raise E_FAIL
Exit Sub
Else
If Not m_fSafeForScripting Then
Err.Raise E_FAIL
End If
Exit Sub
End If Case IID_IPersistStorage, IID_IPersistStream, _
IID_IPersistPropertyBag
If ((dwEnabledOptions And dwOptionsSetMask) <> _
INTERFACESAFE_FOR_UNTRUSTED_DATA) Then
Err.Raise E_FAIL
Exit Sub
Else
If Not m_fSafeForInitializing Then
Err.Raise E_FAIL
End If
Exit Sub
End If Case Else
Err.Raise E_NOINTERFACE
Exit Sub
End Select
End If
End Sub
保存后,把工程编译成OCX文件。现在控件已经实现了IObjectSafety 接口。在.htm中加入这件控件试一试吧。
实现这个 IobjectSafety接口 就不会有警告了 ...
在微软的那篇文章有这么一段:
编译和注册控件后,在注册表中找到以下项:
HKEY_CLASSES_ROOT\Component
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4} HKEY_CLASSES_ROOT\Component
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4} HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4} HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}楼主有没有找到呢?
在classview下,向目录的第一个.h文件(即App启动头文件)中加入以下内容://创建Component Categories中的初始化安全和脚本安全项
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
//在CLSID中创建与Component Categories中初始化安全和脚本安全项中相对应的implemented Categories项
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);
//注销与CLSID中的相应implemented Categories项,一般用不到,因为其它程序可能也会用到这此项
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid);extern const GUID CDECL _tlid;
extern const GUID CDECL CLSID_SafeItem;extern const WORD _wVerMajor;
extern const WORD _wVerMinor;在对就的.cpp文件中加入以下内容,如果原来程序中已经有的,只改动其中的多余部分即可://设置控件与注册表相关的类型库ID,后面跟有version(1.0)字样,从本工程的.idl文件中获取
const GUID CDECL BASED_CODE _tlid =
{ 0xB926A326, 0xBE91, 0x4337, { 0xA1, 0xDC, 0x76, 0x1B, 0x73, 0x15, 0x6B, 0x23 } };
//控件在注册表中的CLSID,后面跟有control字样,从本工程的.idl文件中获取
const GUID CDECL CLSID_SafeItem =
{ 0xAF546E3F, 0xB5B8, 0x42D6, {0xBB, 0x74, 0x84, 0xB7, 0x25, 0xC0, 0x38, 0x4D}};const WORD _wVerMajor = 1;
const WORD _wVerMinor = 0;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);
//创建脚本安全“补充”项,非CLSID中
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 - Removes entries from the system registrySTDAPI 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(CLSID_SafeItem, CATID_SafeForInitializing);
//if (FAILED(hr))
//return hr;
//hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
//if (FAILED(hr))
//return hr; return NOERROR;
}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(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 (FAILED(hr))
return hr;
}
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;
}加入以上代码后IE无任何警告,你可试一下,我用的没问题
我把CLSID_SafeItem 当成_tlid了,晕
编译和注册控件后,在注册表中找到以下项:
HKEY_CLASSES_ROOT\Component
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4} HKEY_CLASSES_ROOT\Component
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4} HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented
Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4} HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented
Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}楼主有没有找到呢?---------------------------
在我的注册表中可以找到这个4个键。但IE还是会弹出警告。不知道是什么原因。我用的XP版SP2.
如果用在internet上同样还是要出现安全提示
最好的办法是去注册一个证书,哈哈
http://www.vckbase.com/document/viewdoc/?id=728
然后是自己的控件类继承IObjectSafetyImpl
class YourClass : public IObjectSafetyImpl<YourClass, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
其中INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA 代表默认这个控件是脚本安全而且初始化安全的。然后在com接口表中添加接口名
BEGIN_COM_MAP(CCGrid)
COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()
可以看一下下面这篇文章:
http://www.cnblogs.com/llf/archive/2006/05/10/ActiveXSafety.html
COM_INTERFACE_ENTRY(IObjectSafety)
public IObjectSafetyImpl<CMyCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER> 更详细的请参见 http://pcfun.com.cn/articles.php?ID=157&item=c 用ATL制作ActiveX控件
IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
END_CATEGORY_MAP()
就可以了楼主
你的问题解决了没?
都跟了这么多帖了!
public IObjectSafetyImpl<CAtlTest, INTERFACESAFE_FOR_UNTRUSTED_CALLER> //这句加在继承类中
COM_INTERFACE_ENTRY(IObjectSafety) //这句加在BEGIN_COM_MAP和END_COM_MAP()中间就可以.
没有证书的话,在网上随便散布一个控件而无提示,你还敢上网吗?