VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • ActiveX控件开发

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  要使用C#实现一个ActiveX控件,需要解决三个问题:

  1.使.NET组件能够被COM调用

  2.在客户机上注册后,ActiveX控件能通过IE的安全认证

  3.未在客户机上注册时,安装包能通过IE的签名认证

  本程序的开发环境是.NET Framework 3.5,工具是Visual Studio .NET 2008,在安装.NET Framework 3.5的客户机上通过测试。

  下面是实现步骤:

  (一)创建可从COM访问的程序集

  首先实现一个对COM可见的程序集,创建类库工程,AssemblyInfo.cs应包含:

usingSystem.Runtime.InteropServices;
//使此程序集中的类型对COM组件可见
[assembly:ComVisible(true)]
//如果此项目向COM公开,则下列GUID用于类型库的ID
[assembly:Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]

  加入以下代码到AssemblyInfo.cs确保程序集的可访问性:

usingSystem.Security;
[assembly:AllowPartiallyTrustedCallers()]

  注意上面的Guid,如果程序集内部的类未标注Guid,COM注册的Guid是会新生成的,此处的Guid没有作用。

  创建用户控件(自定义类待测)IdentityKey.cs,加入:

usingSystem;
usingSystem.ComponentModel;
usingSystem.Windows.Forms;
usingSystem.Runtime.InteropServices;
namespaceKeyActiveX
{
  [Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
  publicpartialclassIdentityKey:UserControl
  {
  }
}

  这里的Guid和AssemblyInfo.cs一样,它会在COM注册中成为CLSID并被html以clsid调用。

 

  类库工程属性中,选择生成,勾选COM注册,在html文件中加入

  <objectid="controlbyid"classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}"></object>

  在IE中启用不安全控件,查看html页面,应能访问到控件,现在一个在发布时对COM注册的程序集开发完成了。

  使用OLE/COM Object Viewer(安装VC自带)可以在.NET Categories中查看组件和CLSID。

  (二)通过IE安全控件认证

  如果客户机的IE未开启访问非安全标记的ActiveX控件,通过IE浏览上面的步骤开发出的ActiveX控件,发现IE会给出警告:

  此页上的 ActiveX 对象可能不安全的。 要允许它将初始化并通过脚本访问吗?

  或禁止访问。这是客户机IE的安全规则设置的,我们应该在控件开发上解决IE安全认证的问题。首先我们要了解IE是如何判断一个ActiveX控件是不安全的,参见Microsoft帮助和支持文档:

  How Internet Explorer Determines If ActiveX Controls Are Safe

  There are two ways to mark a control as safe for scripting and initialization:

  1.Implement the IObjectSafety interface. 

  2.Provide the following registry keys for the control's CLSID under the Implemented Categories section:

  a.The following key marks the control safe for scripting:

  {7DD95801-9882-11CF-9FA9-00AA006C42C4}

  b.The following key marks the control safe for initialization from persistent data:

  {7DD95802-9882-11CF-9FA9-00AA006C42C4} 

  Microsoft recommends that you implement IObjectSafety to mark a control as safe or unsafe. This prevents other users from repackaging your control and marking it as safe when it is not.

 

  我决定实现IObjectSafety接口来向IE表明ActiveX控件的安全标识,以保证控件再次打包时安全标识不会被被改写。

  IObjectSafety是一个COM下的接口,对于C++程序来说,只需要实现它就行了,而.NET之下没有这个接口,在这种情况下,我们的ActiveX控件就是一个不带类型库的COM组件,必须使用C#代码重新定义COM接口。

  这里需要了解一点COM的接口知识。接口是COM的核心,它区分了在客户和对象之间使用的契约和实现。COM的接口有三种类型:定制接口÷分派接口和双重接口。.NET Framework使用ComInterfaceType对它进行了重定义:

namespaceSystem.Runtime.InteropServices
{
  //摘要:
  //  IdentifieshowtoexposeaninterfacetoCOM.
  [Serializable]
  [ComVisible(true)]
  publicenumComInterfaceType
  {
    //摘要:
    //  IndicatestheinterfaceisexposedtoCOMasadualinterface,whichenables
    //  bothearlyandlatebinding.System.Runtime.InteropServices.ComInterfaceType.InterfaceIsDual
    //  isthedefaultvalue.
    InterfaceIsDual=0,
    //
    //摘要:
    //  IndicatesaninterfaceisexposedtoCOMasanIUnknown-derivedinterface,
    //  whichenablesonlyearlybinding.
    InterfaceIsIUnknown=1,
    //
    //摘要:
    //  IndicatesaninterfaceisexposedtoCOMasadispinterface,whichenables
    //  latebindingonly.
    InterfaceIsIDispatch=2,
  }
}

 

  关于三个接口的具体描述,可以参考《C#高级编程第三版》28.1.3 接口。

  在MSDN上查找,可以知道IObjectSafety继承自IUnknown,是一个定制接口;通过上一章节,可以发现向COM注册时,需要提供一个Guid作为CLSID来标识程序集中的C#类,事实上在COM中,接口和类型库都是带有Guid作为唯一标识的,分别为IID和typelib id。

  这样,通过在C#编写的接口标上需要的COM接口IID,就可以在注册是向COM表明接口身份了。在Microsoft帮助上查找IObjectSafety定义:

  [
     uuid(C67830E0-D11D-11cf-BD80-00AA00575603),
     helpstring("VBIObjectSafetyInterface"),
     version(1.0)
   ]
   libraryIObjectSafetyTLB
   {
     importlib("stdole2.tlb");
     [
       uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
       helpstring("IObjectSafetyInterface"),
       odl
     ]
     interfaceIObjectSafety:IUnknown{
       [helpstring("GetInterfaceSafetyOptions")]
       HRESULTGetInterfaceSafetyOptions(
            [in] long riid,
            [in] long*pdwSupportedOptions,
            [in] long*pdwEnabledOptions);
       [helpstring("SetInterfaceSafetyOptions")]
       HRESULTSetInterfaceSafetyOptions(
            [in] long riid,
            [in] long dwOptionsSetMask,
            [in] long dwEnabledOptions);
     }
   }

 

  其中的uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064)就是需要的接口IID。

  使用C#编写IObjectSafety:

usingSystem;
usingSystem.Runtime.InteropServices;
namespaceKeyActiveX
{
  [ComImport,Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  publicinterfaceIObjectSafety
  {
    [PreserveSig]
    voidGetInterfacceSafyOptions(
      intriid,
      outintpdwSupportedOptions,
      outintpdwEnabledOptions);
    [PreserveSig]
    voidSetInterfaceSafetyOptions(
      intriid,
      intdwOptionsSetMask,
      intdwEnabledOptions);
  }
}

  InterfaceType中一定要使用ComInterfaceType.InterfaceIsIUnknown,因为IObjectSafety继承自IUnkown。

  接下来是KeyActiveX的接口实现:

namespaceKeyActiveX
{
  [Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
  publicpartialclassIdentityKey:UserControl,IObjectSafety
  {
    #regionIObjectSafety成员
    publicvoidGetInterfacceSafyOptions(intriid,outintpdwSupportedOptions,outintpdwEnabledOptions)
    {
      pdwSupportedOptions=1;
      pdwEnabledOptions=2;
    }
    publicvoidSetInterfaceSafetyOptions(intriid,intdwOptionsSetMask,intdwEnabledOptions)
    {
      thrownewNotImplementedException();
    }
    #endregion
  }
}

 

  通过返回一个已定值来告诉IE控件是安全的。具体参见

  如何在 VisualBasic 控件实现 IObjectSafety

  (三)签名发布

  C#开发的ActiveX控件发布方式有三种:

  制作客户端安装包,分发给客户机安装;

  制作在线安装包,客户机联机安装;

  使用html中object的codebase指向安装包地址。

  前两个比较简单,适合在局域网内实施,生成安装包时需要装Register属性设置为vsdrpCOM;最后一种方式,需要在安装包上进行数字签名,以保证客户机的安全信任。受信任的签名证书应该向证书提供商(如Versign)购买,然后使用签名工具对安装包进行签名。

  下面利用Visual Studio 2008自带的测试证书创建工具MakeCert和签名工具SignTool进行测试,首先创建一个带有公司信息的测试证书,在Visual Studio命令提示符后输入:

makecert-skABC-n"CN=ABCCorporation"f:abccorptest.cer

  在F盘上创建了测试证书。然后输入

signtoolsignwizard

  在Signing Options页面上,选择Custom,定义证书文件的位置,再下一步选择一个加密算法(MD5或SHA1),指定应用程序的名称和描述URL,确认。

  此时ActiveX控件安装包有了一个被标记为未信任的测试证书,需要将IE设置为启用未信任安装程序,在html中引用

<objectid="controlbyid"classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}"codebase="setup.exe"></object>

  客户机安装之后就可以使用ActiveX控件了。

 

 

  类库工程属性中,选择生成,勾选COM注册,在html文件中加入

  <objectid="controlbyid"classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}"></object>

  在IE中启用不安全控件,查看html页面,应能访问到控件,现在一个在发布时对COM注册的程序集开发完成了。

  使用OLE/COM Object Viewer(安装VC自带)可以在.NET Categories中查看组件和CLSID。

  (二)通过IE安全控件认证

  如果客户机的IE未开启访问非安全标记的ActiveX控件,通过IE浏览上面的步骤开发出的ActiveX控件,发现IE会给出警告:

  此页上的 ActiveX 对象可能不安全的。 要允许它将初始化并通过脚本访问吗?

  或禁止访问。这是客户机IE的安全规则设置的,我们应该在控件开发上解决IE安全认证的问题。首先我们要了解IE是如何判断一个ActiveX控件是不安全的,参见Microsoft帮助和支持文档:

  How Internet Explorer Determines If ActiveX Controls Are Safe

  There are two ways to mark a control as safe for scripting and initialization:

  1.Implement the IObjectSafety interface. 

  2.Provide the following registry keys for the control's CLSID under the Implemented Categories section:

  a.The following key marks the control safe for scripting:

  {7DD95801-9882-11CF-9FA9-00AA006C42C4}

  b.The following key marks the control safe for initialization from persistent data:

  {7DD95802-9882-11CF-9FA9-00AA006C42C4} 

  Microsoft recommends that you implement IObjectSafety to mark a control as safe or unsafe. This prevents other users from repackaging your control and marking it as safe when it is not.



相关教程