因为最近的项目可能会用到调用外部设备,读取信息。为了和现有的BS系统兼容,并以较小的代价满足需求,于是想到了使用ActiveX技术(也有人建议使用Silverlight),这技术虽然比较早了,但还是能够满足目前的需求的

所以在网上找了找资料看看,折腾了两天,总算有点效果了

现在记录一下大致的过程

1、创建一个类库,用于生成ActiveX组件

  A、实现IObjectSafety接口

    [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);
}

  B、实现IOleClientSite接口

    [ComImport, Guid("00000118-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleClientSite
{
void SaveObject();
void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk);
void GetContainer(out IOleContainer ppContainer);
void ShowObject();
void OnShowWindow(bool fShow);
void RequestNewObjectLayout();
}

  C、实现IOleContainer接口

    [ComImport, Guid("0000011B-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleContainer
{
void EnumObjects([In, MarshalAs(UnmanagedType.U4)] int grfFlags,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] ppenum);
void ParseDisplayName([In, MarshalAs(UnmanagedType.Interface)] object pbc,
[In, MarshalAs(UnmanagedType.BStr)] string pszDisplayName,
[Out, MarshalAs(UnmanagedType.LPArray)] int[] pchEaten,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] ppmkOut);
void LockContainer([In, MarshalAs(UnmanagedType.I4)] int fLock);
}

其中A为ActiveX组件必需,

B和C是为了与页面中的JS进行交互

以下为A在组件中的实现

#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 = ;
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 = ;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = ;
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

以下为B和C的使用(这是使用的一个示例,可以根据需要自行处理)

#region CallJavaScript

        private void CallJavaScript(string Filenames)

        {
Type typeIOleObject = this.GetType().GetInterface("IOleObject", true); object oleClientSite = typeIOleObject.InvokeMember(
"GetClientSite",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
this,
null); IOleClientSite oleClientSite2 = oleClientSite as IOleClientSite; IOleContainer pObj; oleClientSite2.GetContainer(out pObj); //参数数组 object[] args = new object[]; args[] = Filenames; //获取页面的Script集合 IHTMLDocument pDoc2 = (IHTMLDocument)pObj; object script = pDoc2.Script; try {
//调用JavaScript方法OnScaned并传递参数,因为此方法可能并没有在页面中实现,所以要进行异常处理
script.GetType().InvokeMember(
"OnScaned",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
script,
args);
}
catch { }
} #endregion CallJavaScript

上面的代码基本上就是ActiveX实现的内容了,再实现自己一些Public方法就可以了,下面说说如何打包

(一些设置之类的,网上都有说)

        /// <summary>
/// 获取客户端主机的MAC地址
/// </summary>
/// <returns></returns>
public string GetMacAddress()
{
var mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
var mos = mc.GetInstances();
var sb = new StringBuilder(); foreach (ManagementObject mo in mos)
{
var macAddress = mo["MacAddress"]; if (macAddress != null)
sb.AppendLine(macAddress.ToString());
} return sb.ToString();
}

  另见:注意事项

  附件:

    CAB打包工具

    自签名证书工具

C#创建ActiveX的更多相关文章

  1. 如何用ATL创建ActiveX控件

    演示截图: 代码简介或代码解析: 如何用ATL创建ActiveX控件 实现了一个ActiveX控件,它在一个圆内部有个正多边形,当用户在多变形内部单击将会使多边形的边数在当前的基础上+1,在多变形外部 ...

  2. 用ATL和MFC来创建ActiveX控件

    摘要:目前MFC和ATL代表了两种框架,分别面向不同类型的基于Windows的开发.MFC代表了创建独立的Windows应用的一种简单.一致的方法:ATL提供了一种框架来实现创建COM客户机和服务器所 ...

  3. VS2017 ATL创建ActiveX编程要点

    VS2017 ATL创建ActiveX控件编程要点: 一.创建vs项目需要安装器visual studio installer中: 安装 visual studio扩展开发中的 用于x86和x64的V ...

  4. Delphi创建ActiveX控件,实现安全接口及无界面代码

    Delphi创建OCX控件非常的方便,但IE调用时弹出的安全认证非常麻烦,有时OCX也不需要界面,IE调用时需要隐藏,非常不方便.在DELPHI中创建OCX实现安全接口和创建事件中修改部分代码 实现安 ...

  5. .net创建activex实现摄像头拍照

    using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices ...

  6. 其它 用VB6创建ActiveX.dll

    1.打开VB6 2.选择 ActiveX DLL,点击打开 3.在窗口输入测试代码 Public Function addstr(str As String) As String addstr = & ...

  7. 【VS开发】动态创建ActiveX控件

    bool CCollectDataDlgDlg::CreateMyCtrl(LPRECT lpRect, UINT nID, CWnd *pParent) {  CLSID clsid;  wstri ...

  8. 让动态创建的ActiveX控件响应Windows消息

    当我们通过 CWnd::CreateControl() 动态创建 ActiveX   控件时, Windows 消息并不会被发送给我 们的由   CWnd 派生得控件类.例如,即使我们为 WM_KIL ...

  9. [ActiveX]使用VS2010创建MFC ActiveX工程项目

    ActiveX的基本概念 ActiveX控件可以看作是一个极小的服务器应用程序,它不能队列运行,必须嵌入到某个容器程序中,与该容器一起运行.这个容器包括web网页,应用程序窗体等等. ActiveX控 ...

随机推荐

  1. 20175221 《Java程序设计》第5周学习总结

    20175221   <Java程序设计>第5周学习总结 教材学习内容总结 接口的定义 接口声明:interface 接口名 接口体中只可以有常量,而没有变量 接口体中只有抽象方法(可省略 ...

  2. P2518 [HAOI2010]计数

    题目链接 \(Click\) \(Here\) 很好很妙的一个题目. 其实可以生成的数字,一定是原数的一个排列,因为\(0\)被放在前面就可以认为不存在了嘛~.也就是说现在求的就是全排列中所有小于该数 ...

  3. Python之路(第十七篇)logging模块

    一.logging模块 (一).日志相关概念 日志是一种可以追踪某些软件运行时所发生事件的方法.软件开发人员可以向他们的代码中调用日志记录相关的方法来表明发生了某些事情.一个事件可以用一个可包含可选变 ...

  4. 前向分步算法 && AdaBoost算法 && 提升树(GBDT)算法 && XGBoost算法

    1. 提升方法 提升(boosting)方法是一种常用的统计学方法,在分类问题中,它通过逐轮不断改变训练样本的权重,学习多个分类器,并将这些分类器进行线性组合,提高分类的性能 0x1: 提升方法的基本 ...

  5. SpringBoot系列: 单元测试2

    之前发了SpringBoot 单元测试的博客, https://www.cnblogs.com/harrychinese/p/springboot_unittesting.html , 内容较少, 现 ...

  6. axd文件

    ashx与axd作用相同,ashx一般在本项目内,axd在其它dll中.axd扩展名的必须要在web.config中的<httpHandlers>中进行注册,而ashx直接在项目中当成as ...

  7. @RequestParam,@PathParam,@PathVariable等注解区别

    @RequestParam 和 @PathVariable 注解是用于从request中接收请求的,两个都可以接收参数,关键点不同的是@RequestParam 是从request里面拿取值,而 @P ...

  8. XSS攻击常识及常见的XSS攻击脚本汇总

    一.什么是XSS? XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了. 这里我们主要注 ...

  9. java8 list和map的forEach

    list forEach示例 public class HelloWorld { public static void main(String[] args) { List<User> l ...

  10. JAVA进阶9

    间歇性混吃等死,持续性踌躇满志系列-------------第9天 1.使用throw语句抛出异常 在通常情况下,程序发生错误时系统会自动抛出异常,而有时希望程序自动抛出异常,可以使用throw语句来 ...