要使用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应包含:

using System.Runtime.InteropServices;

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

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

using System.Security;

[assembly: AllowPartiallyTrustedCallers()]

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

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

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace KeyActiveX
{
    [Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
    public partial class IdentityKey : UserControl
    {
    }
}

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

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

<object id="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对它进行了重定义:

namespace System.Runtime.InteropServices
{
    // 摘要:
    //     Identifies how to expose an interface to COM.
    [Serializable]
    [ComVisible(true)]
    public enum ComInterfaceType
    {
        // 摘要:
        //     Indicates the interface is exposed to COM as a dual interface, which enables
        //     both early and late binding. System.Runtime.InteropServices.ComInterfaceType.InterfaceIsDual
        //     is the default value.
        InterfaceIsDual = 0,
        //
        // 摘要:
        //     Indicates an interface is exposed to COM as an IUnknown -derived interface,
        //     which enables only early binding.
        InterfaceIsIUnknown = 1,
        //
        // 摘要:
        //     Indicates an interface is exposed to COM as a dispinterface, which enables
        //     late binding only.
        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("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);
           }
       }

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

使用C#编写IObjectSafety:

using System;
using System.Runtime.InteropServices;

namespace KeyActiveX
{
    [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IObjectSafety
    {
        [PreserveSig]
        void GetInterfacceSafyOptions(
            int riid,
            out int pdwSupportedOptions,
            out int pdwEnabledOptions);

[PreserveSig]
        void SetInterfaceSafetyOptions(
            int riid,
            int dwOptionsSetMask,
            int dwEnabledOptions);
    }
}

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

接下来是KeyActiveX的接口实现:

namespace KeyActiveX
{
    [Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
    public partial class IdentityKey : UserControl, IObjectSafety
    {
        #region IObjectSafety 成员

public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
        {
            pdwSupportedOptions = 1;
            pdwEnabledOptions = 2;
        }

public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
        {
            throw new NotImplementedException();
        }

#endregion
    }
}

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

如何在 VisualBasic 控件实现 IObjectSafety

(三)签名发布

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

  1. 制作客户端安装包,分发给客户机安装;
  2. 制作在线安装包,客户机联机安装;
  3. 使用html中object的codebase指向安装包地址。

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

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

makecert -sk ABC -n "CN=ABC Corporation" f:\abccorptest.cer

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

signtool signwizard

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

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

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

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

转载于:https://www.cnblogs.com/RCFans/archive/2008/11/15/1333982.html

ActiveX控件开发相关推荐

  1. VB6.0 ActiveX 控件开发详解 [第一章:创建工程]

    前言 在CSDN的VB论坛上,我总是能够看见有人这样问"有没有这样的控件,一个列表框,每一个项前面有一个按钮"(这是例子),又或者见到这样:"怎么样做一个ActiveX控 ...

  2. 使用ActiveX控件开发网页常见的问题

    1. 什么是ActiveX 控件? Microsoft® ActiveX™ 控件是由软件提供商开发的可重用的软件组件.使用 ActiveX控件,可以很快地在网址.台式应用程序.以及开发工具中加入特殊的 ...

  3. ActiveX控件开发总结

    创建ActiveX工程: 可以使用VC建立MFC工程或者ATL工程来进行ActiveX控件开发.使用MFC方式建立,系统会自动实现一些ActiveX控件必须的接口,开发人员只需关注业务就可以了:使用A ...

  4. VC ActiveX 控件 开发总结

    VC 制作ActiveX 控件(OCX) http://ileson.iteye.com/blog/1002910 1.vc6下建立一下activeX工程     详见http://hi.baidu. ...

  5. Visual Studio 2012 C# ActiveX控件开发总结

    目  录 一.ActiveX控件的开发 二.ActiveX控件的部署 三.测试 四.ActiveX控件打包(.cab)与客户端自动安装 ActiveX 控件以前也叫做OLE 控件或OCX 控件,它是一 ...

  6. ActiveX控件开发(转)

    linek: http://www.cnblogs.com/RCFans/archive/2008/11/15/1333982.html 要使用C#实现一个ActiveX控件,需要解决三个问题: 1. ...

  7. ActiveX控件开发总结(续二)

    开发过程中一些经验总结 以下总结主要由李俊峰(lijunfeng 00165774/huawei,).李伟(liwei 00165242/huawei,).姜川(j00132245)总结 1.自定义C ...

  8. 基于MFC的ActiveX控件开发

    转自:http://www.cnblogs.com/lidabo/archive/2012/12/04/2800921.html ActiveX 控件是基于组件对象模型 (COM) 的可重用软件组件, ...

  9. C# ActiveX控件开发_1494

    要使用C#真隐一个ActiveX控件,须要解决三个答题: 1.使.NET组件可以被COM调用 2.在客户机上注册后,ActiveX控件能通功IE的平安认证 3.已在客户机上注册时,安装包能通过IE的签 ...

最新文章

  1. pythonvbb转换txt_Caltech行人数据集转化VOC数据集
  2. [C++] vector 定义和初始化
  3. Python装饰器之property()详解
  4. maven设置本地仓库路径
  5. 统计学习方法 第九章笔记: EM 算法
  6. [html] 写一个水平竖直居中的弹窗,带遮罩层的布局
  7. MIP 支付组件,支付流程:
  8. 减治法在排序算法中的应用(JAVA)--插入排序
  9. 关于EFCore线程内唯一
  10. 工信部召开行政指导会 要求腾讯阿里9月17日前解除屏蔽网址链接
  11. 真不是炼丹,务实敢为的 MoCo v3
  12. python小熊代码_Android开源项目-小熊日记讲解【附源码】
  13. 前端实现video播放
  14. 环境工程学期末复习完整版
  15. 基于朴素贝叶斯算法实现情感分类
  16. 关于Git这一篇就够了
  17. Codeforces Round #439 (Div. 2) E. The Untended Antiquity (hash+数状数组)
  18. gitlab ce 7部署问题小结
  19. PCIe物理层详细总结-PCIe专题知识(一)
  20. 李航《统计学习方法》第二版 实战(mnist为例)

热门文章

  1. Mac软件打不开的解决方法
  2. matlab怀特检验,Eviews8.0多元回归后怀特检验有异方差,如何修正?
  3. 台式电脑开机跳出来计算机,电脑开机出现DHCP怎么办?开机出现DHCP的解决办法...
  4. 【智能零售】2018年新零售商业的四大趋势
  5. 如何把InputStream字节流和InputStreamReader字符流转换成我们能看懂的String字符串
  6. Python--循环语句练习
  7. php ginkgo,Ginkgo: Ginkgo是一个BDD风格的Go测试框架,旨在帮助您有效地编写富有表现力的综合测试...
  8. RISC-V学习笔记【中断和异常】
  9. 详细解读【文件系统】
  10. [Python练习-文件] 多目录下的字幕vtt转srt