若得山花插满头,莫问奴归处!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
           最近应该在一个项目中要限制客户登陆的场地,为此要开发一个ActiveX控件。由于也是第一次在网页中使用ActiveX控件,找了不少资料,不过最终还是完满的把问题解决了。现在在网页中使用AcitiveX控件的还是比较少,应该ActiveX控件对于客户来说存在安全上的问题,一般很难让客户接受同时加之一些浏览器会自动限制,要开发一个能够让客户端能够自动安装使用的AcitiveX控件起码的做两件事:一在代码中将控件注册为安全控件,二为控件加入数字签名还得受信用才行。我开发的这个控件基本上实现了,这个两项只是在数字签名上只是用工具加入一个数字签名,但还是没能使它受信用.下面来讲讲我这个ActiveX控件的实现过程吧:

一 使控件实现 IObjectSafety 接口

   1. 从 Visual Basic 6.0 光盘获取 OLE 自动化类型库生成器。 要这样做, 将所有四个文件从 "Common"Tools"VB"Unsupprt"Typlib" 文件夹复制到项目文件夹。 注意 : VIsual Basic 5.0 中 "VB5.0"Tools"Unsupprt"Typlib" 文件夹中复制所有文件。

  2. 将以下文本复制到记事本, 并作为 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);}}

       3. 创建可保存所有文件, 本示例中创建新文件夹。

      4. 从 Visual Basic 6.0 光盘获取 OLE 自动化类型库生成器。 要这样做, 将所有四个文件从"Common"Tools"VB"Unsupprt"Typlib" 文件夹复制到项目文件夹。 注意 : VIsual Basic 6.0 中 "VB6.0"Tools"Unsupprt"Typlib" 文件夹中复制所有文件。
3. 将以下文本复制到记事本, 并作为 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);
           }}

    4. 在命令提示符处, 使用 CD < 路径 > 命令移到项目文件夹, 然后键入以下命令以生成 .tlb 文件:
MKTYPLIB objsafe.odl /tlb objsafe.tlb
5. 从vb中新建ActiveX控件项目
6. 在 项目 菜单上, 单击 引用 , 浏览并添加 Objsafe.tlb, 它前面创建。
7. 向使用以下代码, 项目添加一个新模块并命名模块 basSafeCtl:      

Model Code 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 LongByVal cbMax As IntegerAs Long

      
Public Type udtGUID
          Data1 
As Long
          Data2 
As Integer
          Data3 
As Integer
          Data4(
7As Byte
      
End Type

      
Public m_fSafeForScripting As Boolean
      
Public m_fSafeForInitializing As Boolean

      
Sub Main()
          m_fSafeForScripting 
= True
          m_fSafeForInitializing 
= True
      
End Sub


8.从 ProjectProperties@@, Startup 对象更改到要执行上述 SubMain SubMain 。 使用 m_fSafeForScripting 和 m_fSafeForInitializing 变量来指定安全执行脚本和/或初始化变量的值。
9.打开控件的代码窗口。 将下列行的代码添加到声明部分 (OptionExplicit 后或作为第):Implements IObjectSafety
10.新建一个模块复制下面两个过程到模块

Two Function 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 <> 0Then
              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 _
      
LongByVal dwOptionsSetMask As LongByVal dwEnabledOptions As Long)
          
Dim Rc          As Long
          
Dim rClsId      As udtGUID
          
Dim IID         As String
          
Dim bIID()      As Byte

          
If (riid <> 0Then
              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


11在 文件 菜单上, 保存您的项目和文件。 生成 OCX 文件从项目。 现在您控件实现 IObjectSafety 接口。
到此为止你已实现了一个标记为安全控件的ActiveX控件,你可以试试没有实现IObjectSafety 接口的控件的差别。

二.为控件加入数字签名,要加入数字签名你需要一下工具: 

1使用makecert.exe创建私钥和证书

 格式:makecert –sv YourPrivateName.pvk -ss Yourname –n “CN-YourName” YourCerName.cer执行命令将生产两个文件私钥YourPrivateName.pvk和证书:YourCerName.cer。

2使用signcode.exe将证书附件到ActiveX控件中(如果你在网页中是控件打包成cab,你也可以直接将证书附件到安装包上),运行后会有一个可视化的界面让你选择要控件和证书和私钥。

这样就完成了数字签名。

三在网页中加入ActiveX控件

<OBJECT

CLASSID="CLSID:DEE4306A-8D4A-4070-B1E6-EB08516101C0"

CODEBASE="YourActiveX.ocx#version=1,0,0,0" id="ScNO" name ="ScNO" height="15px" width="25px">

</OBJECT>

4306A-8D4A-4070-B1E6-EB08516101C0"

CODEBASE="YourActiveX.ocx#version=1,0,0,0" id="ScNO" name ="ScNO" height="15px" width="25px">

</OBJECT>

DEE4306A-8D4A-4070-B1E6-EB08516101C0为你控件在注册表中的CLSID值:当你用vb编译是自动注册到注册表中了你可以HKEY_CLASSES_ROOT查找,CODEBASE放的是你要被客户下载的控件路径和版本,当客户端的控件版本和这个不同是就会让客户安装。

调用控件中的方法:

 <script language="javascript" type="text/javascript">

function GetDeriveID()

 {

 try

 {

 var Ctrl=document.getElementById ("ScNO");

 if(Ctrl!=null)

 {

   var Msg=Ctrl.GetYourFun();

   alert("调用成功");

 }

 else

 {

   alert("调用失败");

   }

</script>

到现在为止你已可以发布你的网页了让在客户端试试会不会自动安装,如果没有客户端没有限制那么就能自动安装。如果万一不能自动安装你还可以写个程序让客户下载安装,我是写了一个批处理程序,来注册控件的。很简单:

注册:

@echo off

"regsvr32" " YourActiveX.ocx"

取消注册:

@echo off

"regsvr32" "-u" "SMCActX.ocx"

大家如果在开发中要用户ActiveX控件不妨参考一下,可省去不少弯路。

posted on 2008-02-25 15:19  莫问奴归处  阅读(7343)  评论(0编辑  收藏  举报
轩轩娃