C#开发ActiveX控件

[转自]原文地址:http://www.cnblogs.com/yilin/p/csharp-activex.html
[转自]原文地址:https://www.cnblogs.com/zhouxiaoyun/p/5801196.html
[转自]原文地址:https://jingyan.baidu.com/article/8ebacdf010ba2c49f65cd5aa.html

前言

网页本身的功能是有限的,要想实现一些网页本身不支持的功能,就需要用到ActiveX控件。
ActiveX控件以前也叫做OLE控件,它是微软IE支持的一种软件组件或对象,可以将其插入到Web页面中,实现在浏览器端执行动态程序功能,以增强浏览器端的动态处理能力。通常ActiveX控件都是用C++或VB语言开发,本文介绍另一种方式,在.NET Framework平台上,使用C#语言开发ActiveX控件。

严格意义上讲,c#是不能生成纯正ocx控件的,我们在vs.net中新建项目时,也找不到专门的"ActiveX项目"新建项,最多也只就能新 建"类库"得到一个dll而非ocx(因此我们也无法用传统的regsvr32来注册该dll),但是c#能开发com组件,activeX控件本质上讲 跟com是一类技术,所以用c#开发"能够让网页调用的com类库"还是可行的。

虽然本文通篇都在讲如何使用C#语言开发ActiveX控件,但我并不极力推荐使用这种技术,因为该技术存在明显的局限,即需要浏览器端安装.NET Framework(版本取决于开发ActiveX控件使用的.NET Framework版本),该局限对于挑剔的互联网用户,几乎是不可接受的。所以,我建议以下几条均满足时,方可考虑使用该技术:

  • 开发团队中没有人掌握使用C++/VB开发ActiveX控件技术;
  • 该ActiveX控件不用于互联网;
  • 用户对仅能使用IE浏览器访问表示可以接受;
  • 用户对在浏览器端安装.NET Framework组件表示可以接受。

另外,我建议如果不是因为控件的依赖库基于更高版本的.NET Framework,或需要更高版本的.NET Framework提供的扩展功能(如需要WCF等),尽量在.NET Framework 2.0上开发ActiveX控件,因为.NET Framework 2.0只有20M,相比300M的.NET Framework 3.5和40M的.NET Framework 4.0都要小很多,对客户端操作系统的要求也要低很多,并且随着Windows版本的不断升级换代,Windows Vista以后的版本已经内置了.NET Framework 2.0。等到Windows XP系统寿终正寝之时,也将迎来该技术的春天。所以,别被我上面的建议夯退了,掌握该技术其实还是蛮有实用价值的,毕竟,C#高效的开发效率很有吸引力。

本文接下来将使用C#语言开发一个ActiveX控件,实现对浏览器端的MAC地址遍历功能;另外,提供一个在Web静态页面中调用该控件的测试实例。
本实例的开发环境为Visual Studio 2013,目标框架为.NET Framework 2.0;浏览器端测试环境为Windows 7旗舰版,IE9。

步骤

首先,新建一个类库工程(也可以是windows窗体控件库),右键工程属性,在“应用程序”页,点击“程序集信息”按钮,在弹出的窗体里勾选“使程序集COM可见”,具体操作如下图
在这里插入图片描述
第二步,切换到“生成”的选项卡,勾选“为COM互操作注册”,如下图
在这里插入图片描述
第三步,在AssemblyInfo.cs里添加[assembly: AllowPartiallyTrustedCallers()],需要引用using System.Security;命名空间
在这里插入图片描述
ActiveX类库的内容大致包括两部分,IObjectSafety接口和实现该接口的控件类。考虑所有控件类都要实现IObjectSafety接口,可以将该接口的实现抽象为一个控件基类。

第四步,添加一个IObjectSafety的接口,添加IObjectSafety.cs,这里的名字不要改它,这个接口主要是在浏览器中提高控件的可信任度。
在这里插入图片描述
接口里面的内容如下,特别注意的是这里面的guid 不能更改,只要将下面的代码复制到接口里面去就可以了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace HuaYun.ActiveX
{
    [ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IObjectSafety
    {
        [PreserveSig]
        int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);

        [PreserveSig()]
        int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
    }
}

ActiveXControl控件基类,实现IObjectSafety接口(可以在控件类中实现,这里单独做一个基类,方便其他控件类继承)

public abstract class ActiveXControl : IObjectSafety
{
    #region IObjectSafety 成员

    private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
    private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
    private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
    private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
    private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";

    private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
    private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
    private const int S_OK = 0;
    private const int E_FAIL = unchecked((int)0x80004005);
    private const int E_NOINTERFACE = unchecked((int)0x80004002);

    private bool _fSafeForScripting = true;
    private bool _fSafeForInitializing = true;


    public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
    {
        int Rslt = E_FAIL;

        string strGUID = riid.ToString("B");
        pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
        switch (strGUID)
        {
            case _IID_IDispatch:
            case _IID_IDispatchEx:
                Rslt = S_OK;
                pdwEnabledOptions = 0;
                if (_fSafeForScripting == true)
                    pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                break;
            case _IID_IPersistStorage:
            case _IID_IPersistStream:
            case _IID_IPersistPropertyBag:
                Rslt = S_OK;
                pdwEnabledOptions = 0;
                if (_fSafeForInitializing == true)
                    pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                break;
            default:
                Rslt = E_NOINTERFACE;
                break;
        }

        return Rslt;
    }

    public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
    {
        int Rslt = E_FAIL;

        string strGUID = riid.ToString("B");
        switch (strGUID)
        {
            case _IID_IDispatch:
            case _IID_IDispatchEx:
                if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
                        (_fSafeForScripting == true))
                    Rslt = S_OK;
                break;
            case _IID_IPersistStorage:
            case _IID_IPersistStream:
            case _IID_IPersistPropertyBag:
                if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
                        (_fSafeForInitializing == true))
                    Rslt = S_OK;
                break;
            default:
                Rslt = E_NOINTERFACE;
                break;
        }

        return Rslt;
    }

    #endregion
}

第五步,添加一个用户控件UserControl.cs,并让这个控件继承ActiveXControl控件基类,同时在这个控件的类中加上一个Guid的特性,如:[Guid(“21209360-34E1-423E-A81F-BC80B62021B7”)],注意,后面在html页面中要根据这个Guid注册控件的
在这里插入图片描述
在这里插入图片描述
看看UserControl.cs里的内容

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Preresearch.CSharpActiveX;
using System.Runtime.InteropServices;//必须引用,下面的guid属性才能使用
namespace WindowsFormsControlLibrary1
{
    //通过工具-〉创建GUID-〉选择GUID格式5生成,在网页引用控件时
    //,指定的ID必须是这个ID,指定安装包为将此动态库打包后的安装包,网页和安装包放在同一目录下
    [Guid("4282835D-C8A3-4EA1-A62F-D422DE23DBDA")]

    public partial class UserControl1 : UserControl, ActiveXControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "aaa";
        }
    }
}

到这一步,ActiveX控件基本上是开发完成了,可以呈现了,新建个Html页面,在页面上加入下面一行代码,ID使用上面生成的控件GUID,将html和setup.exe(或者直接使用未打包的dll)放在同一目录下,生成ActiveX控件的解决方案,注意:后面每次生成的时候都要关闭在页面中有用到这个控件的页面,不然会占这进程,生成不了

<object id="activex" classid="clsid:21209360-34E1-423E-A81F-BC80B62021B7" codebase="/setup.exe" width="100%" height="200"></object>

其中classid就是上面的ActiveXControl类里加的Guid的特性里的Guid值,codebase是后面打包成安装文件放在站点目录里的安装文件。

接下来将项目打包成安装文件,具体步骤参考:
https://blog.csdn.net/weixin_43926268/article/details/100020108

再接下来就是签名打包cab文件等, 以便浏览器自动下载安装插件。

最后感谢原博主的文章,如有侵权,请联系删除!
博主码字不易,转载请注明原出处。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值