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/, 试过,但还是不行,不知道什么原因。请大家帮忙!

解决方案 »

  1.   

    如何在VB中实现ActiveX控件的IobjectSafety接口  
    总述
    本文叙述了如何在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中加入这件控件试一试吧。
      

  2.   

    就是在你的 控件生成的时候,
    实现这个 IobjectSafety接口 就不会有警告了 ...
      

  3.   

    谢谢楼上的,我是用mfc写控件的,能不能介绍MFC下面的处理方法,谢谢了
      

  4.   

    konj()能说的详细一点吗?
      

  5.   

    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/, 试过,但还是不行,不知道什么原因。----------------------------------------------------------------------------------------------
    在微软的那篇文章有这么一段:
    编译和注册控件后,在注册表中找到以下项:    
    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}楼主有没有找到呢?
      

  6.   

    我用这种方法只找到前面两个KEY, 不知道怎么回事现在我用实现IobjectSafety接口的方法解决了,但不是很懂里面的原理。如果有朋友很熟的话,可以解释一下,分照算阿!!
      

  7.   

    我用的是这种方法:
       在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无任何警告,你可试一下,我用的没问题
      

  8.   

    楼上的,谢谢你!!
    我把CLSID_SafeItem 当成_tlid了,晕
      

  9.   

    在微软的那篇文章有这么一段:
    编译和注册控件后,在注册表中找到以下项:    
    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.
      

  10.   

    据说是实现ISafeObject,还有就是属性注册两种,都实现过,在n年前还好用,现在还是这样。不过对于现在的IE来说,都需要把ie安全设置为中级才可以。
      

  11.   

    vs6.0 带的msdn 6.0 教程 ATL Tutorial 就有讲,去看一下
      

  12.   

    给ActiveX签名,和实现IObjectSaftey接口,只能说在局域网内不出现那样的提示
    如果用在internet上同样还是要出现安全提示
    最好的办法是去注册一个证书,哈哈
      

  13.   

    请参阅:编写在浏览器中不弹出警告的ActiveX控件
    http://www.vckbase.com/document/viewdoc/?id=728
      

  14.   

    如果你的ActiveX控件是用在Internet上的,那只能去注册一个证书,这样IE才会认为你的控件是安全的,才不弹出那个警告框。
      

  15.   

    首先包含头文件 #include "objsafe.h"
    然后是自己的控件类继承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
      

  16.   

    .day day up,good good study.
      

  17.   

    http://msdn.microsoft.com/workshop/components/activex/safety.asp
      

  18.   

    只需在你的工程相应位置分别加上这两行,问题就解决了:
    COM_INTERFACE_ENTRY(IObjectSafety)
    public IObjectSafetyImpl<CMyCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER> 更详细的请参见 http://pcfun.com.cn/articles.php?ID=157&item=c 用ATL制作ActiveX控件
      

  19.   

    加上BEGIN_CATEGORY_MAP(yourclass)
    IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
    IMPLEMENTED_CATEGORY(CATID_SafeForScripting) 
    END_CATEGORY_MAP()
    就可以了楼主
    你的问题解决了没?
    都跟了这么多帖了!
      

  20.   

    只需在你的工程相应位置分别加上这两行,问题就解决了:
    public IObjectSafetyImpl<CAtlTest, INTERFACESAFE_FOR_UNTRUSTED_CALLER>   //这句加在继承类中
    COM_INTERFACE_ENTRY(IObjectSafety)  //这句加在BEGIN_COM_MAP和END_COM_MAP()中间就可以.
      

  21.   

    楼上的和这位仁兄haolaiwu(宁愿相信世界上有鬼,也不相信女人那张嘴)说的是正道.
    没有证书的话,在网上随便散布一个控件而无提示,你还敢上网吗?