C#创建ActiveX
因为最近的项目可能会用到调用外部设备,读取信息。为了和现有的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();
}
另见:注意事项
附件:
C#创建ActiveX的更多相关文章
- 如何用ATL创建ActiveX控件
演示截图: 代码简介或代码解析: 如何用ATL创建ActiveX控件 实现了一个ActiveX控件,它在一个圆内部有个正多边形,当用户在多变形内部单击将会使多边形的边数在当前的基础上+1,在多变形外部 ...
- 用ATL和MFC来创建ActiveX控件
摘要:目前MFC和ATL代表了两种框架,分别面向不同类型的基于Windows的开发.MFC代表了创建独立的Windows应用的一种简单.一致的方法:ATL提供了一种框架来实现创建COM客户机和服务器所 ...
- VS2017 ATL创建ActiveX编程要点
VS2017 ATL创建ActiveX控件编程要点: 一.创建vs项目需要安装器visual studio installer中: 安装 visual studio扩展开发中的 用于x86和x64的V ...
- Delphi创建ActiveX控件,实现安全接口及无界面代码
Delphi创建OCX控件非常的方便,但IE调用时弹出的安全认证非常麻烦,有时OCX也不需要界面,IE调用时需要隐藏,非常不方便.在DELPHI中创建OCX实现安全接口和创建事件中修改部分代码 实现安 ...
- .net创建activex实现摄像头拍照
using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices ...
- 其它 用VB6创建ActiveX.dll
1.打开VB6 2.选择 ActiveX DLL,点击打开 3.在窗口输入测试代码 Public Function addstr(str As String) As String addstr = & ...
- 【VS开发】动态创建ActiveX控件
bool CCollectDataDlgDlg::CreateMyCtrl(LPRECT lpRect, UINT nID, CWnd *pParent) { CLSID clsid; wstri ...
- 让动态创建的ActiveX控件响应Windows消息
当我们通过 CWnd::CreateControl() 动态创建 ActiveX 控件时, Windows 消息并不会被发送给我 们的由 CWnd 派生得控件类.例如,即使我们为 WM_KIL ...
- [ActiveX]使用VS2010创建MFC ActiveX工程项目
ActiveX的基本概念 ActiveX控件可以看作是一个极小的服务器应用程序,它不能队列运行,必须嵌入到某个容器程序中,与该容器一起运行.这个容器包括web网页,应用程序窗体等等. ActiveX控 ...
随机推荐
- 学习python第二天
编程语言分为哪几种? 1. 机器语言:是通过直接编写二进制指令对计算机下达指令的编程方式 -- 0000,0000,00000000001:加载 暂存区A 存储器地址1 2. 汇编语言:是通过编写二进 ...
- 应用调试(一)strace
目录 编译 使用 原理 深入文档 title: 应用调试(一)strace date: 2019/1/15 23:35:14 toc: true --- 编译 #tar -xjf strace-4.5 ...
- Git 分支 (二)合并
分支的新建与合并 让我们来看一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流. 你将经历如下步骤:1. 开发某个网站.2. 为实现某个新的需求,创建一个分支.3. 在这个分支上开 ...
- 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)
一. 简介 上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据.但本章节重点介绍的三种加载方式均是针对含(导航属性.外键)的情况下 ...
- ArcGis Classic COM Add-Ins插件开发的一般流程 C#
COM add-ins是我对这种开发方式的称呼,Esri的官方文档里称其为“Extending ArcObject”或者“Classic COM extensibility”,Esri所称的addin ...
- latex beamer 添加页码
导言中加 \setbeamertemplate{footline}[frame number]
- luogu 1731 搜索剪枝好题
搜索剪枝这个东西真的是骗分利器,然鹅我这方面菜的不行,所以搜索数学dp三方面是真的应该好好训练一下 一本通的确该认真的刷嗯 #include<bits/stdc++.h> using na ...
- MySQL数据库学习2 - 数据库的操作
一.系统数据库 二.创建数据库 三.数据库相关操作 四.了解内容 一.系统数据库 执行如下命令,查看系统库 show databases; information_schema: 虚拟库,不占用磁盘空 ...
- 使用HttpClient和WebRequest时POST一个对象的写法
[一]步骤: 1)将对象转化为Json字符串. 2)将Json字符串编码为byte数组. 3)设置传输对象(WebRequest或者HttpClient)的ContentType是"appl ...
- Spring系列(四) 面向切面的Spring
除了IOC外, AOP是Spring的另一个核心. Spring利用AOP解决应用横切关注点(cross-cutting concern)与业务逻辑的分离, 目的是解耦合. 横切关注点是指散布于代码多 ...