akyou56 发表于 2015-5-15 08:17:20

win7下VS2010 C# ActiveX控件制作(附原码)

  原码以及makeCAB包下载地址:
  http://files.iyunv.com/zouyang/HelloDaniel.rar
  一、环境:
  操作系统:Win7
  开发工具:Visual Studio 2010
  .NET版本:4.0
  开发语言:C#
  下载makeCAB压缩包,这里面包含了制作数字签名和制作cab的几个exe程序

  保存路径:D:\makeCAB
  需要编辑的系统环境变量设置:(下面的系统变量)

  这样做是为了方便后面在cmd里调用。
  二、编写ActiveX控件
  1、创建一个新的Windows窗体控件库

  2、重命名UserControl1.cs 为HelloDanielActiveX.cs

  3、拖1个GroupBox和2个Label控件到界面上

  4、为控件添加一个方法,用来设置Label中显示当前时间
  #region Javascript调用ActiveX的方法
  // 设置当前时间
  public void SetTime(string timeStr)
  {
  this.label2.Text = timeStr;
  }
  #endregion
  5、新建一个接口


  下面是这个接口的代码:
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Runtime.InteropServices;
  namespace HelloDaniel
  {
  
  
  public interface IObjectSafety
  {
  
  int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions,
   ref int pdwEnabledOptions);
  
  int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask,
   int dwEnabledOptions);
  }
  }
  6、在控件中实现这个接口
  关于实现这个接口,篇幅较长,可以在这篇文章找到:http://www.pinvoke.net/default.aspx/Interfaces/IObjectSafety.html
  7、为控件添加Guid、ProgId和ComVisible属性
  Guid的获得应该是这样的:


  点击复制,然后将你得到的Guid号Copy下,粘贴到下面代码里面。
  然后,右键单击项目HelloDaniel——>属性,在应用程序中选择程序集信息


  把使程序集COM可见的对勾打上。
  同时,在属性——>【生成】项中选择为COM互操作注册




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using mshtml;
using System.Reflection;

namespace HelloDaniel
{// {6DCD51C2-33FD-4556-842F-419B6AA3C252}

public partial class HelloDanielActiveX : UserControl, 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 HelloDanielActiveX()
{
InitializeComponent();
}
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;
}
#region Javascript调用ActiveX的方法
///
/// 设置当前时间
///
///
public void SetTime(string timeStr)
{
this.label2.Text = timeStr;
}
#endregion
#region ActiveX调用Javascript的函数 方法一
///
/// HTMLWindow2Class对象
///
private mshtml.IHTMLWindow2 html = null;
///
/// 调用Javascript
///
///
///
private void button1_Click(object sender, EventArgs e)
{
html.execScript("CallByActiveX('" + this.label2.Text + "');", "javascript");
//CallJavaScript(this.label2.Text);
}
///
/// 将window对象传递进来
///
/// The obj.
public void SetHtml(object obj)
{
html = obj as mshtml.IHTMLWindow2;
}
#endregion
#region ActiveX调用Javascript的函数 方法二
///
/// 调用Javascript
///
/// The filenames.
private void CallJavaScript(string param)
{
//反射获取当前的控件的ClientSite
Type typeIOleObject = this.GetType().GetInterface("IOleObject", true);
object oleClientSite = typeIOleObject.InvokeMember("GetClientSite",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
this,
null);
//获取Container
IOleClientSite oleClientSite2 = oleClientSite as IOleClientSite;
IOleContainer pObj;
oleClientSite2.GetContainer(out pObj);
//参数数组   
object[] args = new object;
args = param;
//获取页面的Script集合   
IHTMLDocument pDoc2 = (IHTMLDocument)pObj;
object script = pDoc2.Script;
try
{
//调用JavaScript方法OnScaned并传递参数,因为此方法可能并没有在页面中实现,所以要进行异常处理   
script.GetType().InvokeMember("ShowNowTime", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
script,
args);
}
catch { }
}
#endregion

}
}

  代码里添加了两个在控件中实现javascript的方法。
  8、为了实现在控件中javascript的调用,需要添加引入
  右键单击项目HelloDaniel——>【添加引用】

  
  9、生成项目,进入到你的项目文件夹bin\debug目录下可以看到

  二、制作ActiveX Setup安装文件
  1、右键解决方案——>添加——>新建项目

  在其他项目类型——>安装和部署——>安装项目

  2、在新建的项目上点右键,【添加】——>【项目输出】,如图操作。

  3、生成项目


  会生成两个安装程序。
  剩下的工作就是打包签名部署到网页上测试了
  三、打包生成cab文件
  1、准备打包文件,建议新建个文件夹用来做cab包
我放在D盘下新建的ActiveX文件夹内



其中install.inf配置文件如下:

signature="$CHICAGO$"
AdvancedINF=2.0

HOOKRUN1=HOOKRUN1

InstallScope=machine

run=%EXTRACT_DIR%\run.bat
run.bat内容如下:
set CURDIR=%cd%
msiexec.exe /i "%CURDIR%\HelloDanielSetup.msi" /qn

  
  2、打包cab
  【开始】——【运行】——输入CMD
  进入你新建的文件夹目录下(ActiveX),输入命令:
  CABARC -s 6144 n HelloDaniel.cab HelloDanielSetup.msi install.inf run.bat

  3、给cab数字签名
  这里我需要求助一下,我在网上发现大家都是自己制作测试证书,但是我自己制作的证书签名后验证确实签名失败的。后来找到一个免费的数字签名工具(DSignTool)v1.7专业版,当然是做测试证书的。实验成功,大家可以下来试试,确实要方便的多,毕竟coder需要不断的测试嘛,下面是下载网址:
  http://www.arpun.com/soft/9388.html
  4、编辑网页测试
  网页代码如下:



!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
页: [1]
查看完整版本: win7下VS2010 C# ActiveX控件制作(附原码)