zoukankan      html  css  js  c++  java
  • c#中开发ActiveX控件

    1.为什么要用ActiveX?

    网页本身的功能是有限的,要想实现一些网页本身不支持的功能。

    2.c#能开发ActiveX吗?

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

    3.开发步骤:

    (1)新建一个类库
    (2)修改项目的"属性",在“应用程序”选项中找到“程序集信息”按钮,点击它,在弹出的界面中勾中“使程序集COM可见(M)”;然后再到“生成”选项中把“输出”中的“为com互操作注册”勾中。

    (3)修改AssemblyInfo.cs,增加[assembly: AllowPartiallyTrustedCallers()],完整内容类似下面这样:

     1 using System.Reflection;
     2 using System.Runtime.CompilerServices;
     3 using System.Runtime.InteropServices;
     4 using System.Security;
     5 
     6 // 有关程序集的常规信息通过下列属性集
     7 // 控制。更改这些属性值可修改
     8 // 与程序集关联的信息。
     9 [assembly: AssemblyTitle("OCXTEST")]
    10 [assembly: AssemblyDescription("")]
    11 [assembly: AssemblyConfiguration("")]
    12 [assembly: AssemblyCompany("")]
    13 [assembly: AssemblyProduct("OCXTEST")]
    14 [assembly: AssemblyCopyright("Copyright ©  2016")]
    15 [assembly: AssemblyTrademark("")]
    16 [assembly: AssemblyCulture("")]
    17 [assembly: AllowPartiallyTrustedCallers()]
    18 
    19 // 将 ComVisible 设置为 false 使此程序集中的类型
    20 // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
    21 // 则将该类型上的 ComVisible 属性设置为 true。
    22 [assembly: ComVisible(true)]
    23 
    24 // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
    25 [assembly: Guid("b7f60d9f-9669-4960-896a-6e53f6a9cf7a")]
    26 
    27 // 程序集的版本信息由下面四个值组成:
    28 //
    29 //      主版本
    30 //      次版本 
    31 //      内部版本号
    32 //      修订号
    33 //
    34 // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
    35 // 方法是按如下所示使用“*”:
    36 // [assembly: AssemblyVersion("1.0.*")]
    37 [assembly: AssemblyVersion("1.0.0.0")]
    38 [assembly: AssemblyFileVersion("1.0.0.0")]
    View Code

    (4)新建一个IObjectSafety接口文件IObjectSafety.cs,内容如下:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.Runtime.InteropServices;
     5 
     6 namespace OCXTEST
     7 {
     8     [ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
     9     [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    10     public interface IObjectSafety
    11     {
    12         [PreserveSig]
    13         int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
    14         [PreserveSig()]
    15         int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
    16     }
    17 }
    View Code

    该内容除命名空间可以更改外,其它内容都是固定的,不要修改
    (5)新建一个:Windows Forms-->“用户控件”,我们的主要逻辑就写在这里(还可以在它上面随便放置其它windows常用控件,跟winForm开发一样),不过首先要修改类定义,让其实现我们刚才定义的接口。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Drawing;
     5 using System.Data;
     6 using System.Linq;
     7 using System.Text;
     8 using System.Windows.Forms;
     9 using System.Runtime.InteropServices;
    10 
    11 namespace OCXTEST
    12 {
    13     [Guid("DD99DBDA-C676-48b9-923E-67C906499353")]
    14     public partial class UserControl1 : UserControl, IObjectSafety
    15     {
    16         public UserControl1()
    17         {
    18             InitializeComponent();
    19         }
    20 
    21         public int add(int a, int b)
    22         {
    23             return a + b;
    24         }
    25 
    26         #region IObjectSafety 成员
    27 
    28         private const string _IID_IDispatch = " {00020400-0000-0000-C000-000000000046} ";
    29         private const string _IID_IDispatchEx = " {a6ef9860-c720-11d0-9337-00a0c90dcaa9} ";
    30         private const string _IID_IPersistStorage = " {0000010A-0000-0000-C000-000000000046} ";
    31         private const string _IID_IPersistStream = " {00000109-0000-0000-C000-000000000046} ";
    32         private const string _IID_IPersistPropertyBag = " {37D84F60-42CB-11CE-8135-00AA004BB851} ";
    33         private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
    34         private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
    35         private const int S_OK = 0;
    36         private const int E_FAIL = unchecked((int)0x80004005);
    37         private const int E_NOINTERFACE = unchecked((int)0x80004002);
    38 
    39         private bool _fSafeForScripting = true;
    40         private bool _fSafeForInitializing = true;
    41 
    42         public int GetInterfaceSafetyOptions(ref Guid riid, ref   int pdwSupportedOptions, ref   int pdwEnabledOptions)
    43         {
    44             int Rslt = E_FAIL;
    45 
    46             string strGUID = riid.ToString(" B ");
    47             pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
    48             switch (strGUID)
    49             {
    50                 case _IID_IDispatch:
    51                 case _IID_IDispatchEx:
    52                     Rslt = S_OK;
    53                     pdwEnabledOptions = 0;
    54                     if (_fSafeForScripting == true)
    55                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
    56                     break;
    57                 case _IID_IPersistStorage:
    58                 case _IID_IPersistStream:
    59                 case _IID_IPersistPropertyBag:
    60                     Rslt = S_OK;
    61                     pdwEnabledOptions = 0;
    62                     if (_fSafeForInitializing == true)
    63                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
    64                     break;
    65                 default:
    66                     Rslt = E_NOINTERFACE;
    67                     break;
    68             }
    69 
    70             return Rslt;
    71         }
    72 
    73         public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
    74         {
    75             int Rslt = E_FAIL;
    76             string strGUID = riid.ToString(" B ");
    77             switch (strGUID)
    78             {
    79                 case _IID_IDispatch:
    80                 case _IID_IDispatchEx:
    81                     if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
    82                         Rslt = S_OK;
    83                     break;
    84                 case _IID_IPersistStorage:
    85                 case _IID_IPersistStream:
    86                 case _IID_IPersistPropertyBag:
    87                     if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
    88                         Rslt = S_OK;
    89                     break;
    90                 default:
    91                     Rslt = E_NOINTERFACE;
    92                     break;
    93             }
    94             return Rslt;
    95         }
    96 
    97         #endregion 
    98     }
    99 }
    View Code

    #region IObjectSafety 成员 ... #endregion这一段的内容是固定的,不要修改,其它内容根据自己的业务要求自行修改,另外类前面要加上Guid的标识,以便网页调用时,能用CLSID="xxx"来调用

    基本上这样弄完后,就可以在网页中,用类似下面这样的代码来本机调用了:

     1 <script type="text/javascript" language="javascript">
     2 
     3     function test() {
     4           var a = csocx.test(2,3);
     5           alert(a);
     6     }        
     7   
     8 </script>
     9 <body>
    10     <object id="csocx" classid="clsid:A648C7F5-65E5-40F5-817D-FCA25C34BC46">
    11     </object>
    12     <input id="c" type="button" value="TEST" onclick="test();" />
    13 </body>
    View Code

    4.安装部署

    前面已经提到了,c#开发的(伪)"ActiveX"控件并非纯正的ocx,所以只能用RegAsm.Exe xxx.dll来进行程序集的注册,这里要注意一点:在开发机上,项目编译后vs.net会自动将bindebugxxx.dll调用regasm注 册,但在别人机器上就不行了,为了能在调试时模拟其它机器的运行结果,可以在编译后,手动用类似 regAsm.exe D:MyDocActiveXDemooutputActiveXDemo.dll /u 来反注册(在vs.net命令行模式下)


    然后在安装项目上,右键"添加"-->"项目输出"-->"主输出"-->在项目下拉框中选择activex所对应的项目即可.

    注意:"主输出来自xxx"的属性栏中,有一个"Register"必须选择"vsdrpCOM"

    另外还有一个问题,可能是我机器的个别现象,每次activex项目有修改时,建议最好手动清除安装项目debug目录下的文件,再重新生成安装项目,否则有时候会发现activex修改了,但是安装包中包含的dll还是未修改过的版本。

    后话:c#开发的东西是运行于.net 框架之上的,就好比java开发的东西必须要java runtime才能运行一样,利用本文方法开发出来的dll也必须要安装.net框架才能跑起来,幸好最新的win7中已经集成了.net框架,当然您如 果对于庞大的.net框架安装程序很敏感,仍然觉得纯正的ocx更好的话,建议还是用vb/delphi/c++这一类老牌的开发工具/语言实现。

    参考链接:http://www.cnblogs.com/yjmyzz/archive/2009/12/14/1623396.html

  • 相关阅读:
    Python Redis 五大数据类型
    Python 魔法方法
    Python 静态方法,类方法,属性方法
    Python 反射
    Python 中 封装,继承,多态
    Redis 事务
    Redis 哨兵集群
    装饰器,迭代器,生成器
    Flume与kafka集成
    hbase 可视化工具 HBaseXplorer---HbaseGUI
  • 原文地址:https://www.cnblogs.com/bobshieh/p/5746844.html
Copyright © 2011-2022 走看看