--资料来源互联网
第一步:创建C#类库项目,修改“名称”为HuaYun.ActiveX
第二步:修改AssemblyInfo.cs,增加代码
//自定添加 [assembly: AllowPartiallyTrustedCallers()]
第三步:右键工程,“添加”-“用户控件”命名为“ActiveXControl.cs”
第四步:按照第三步的方法添加接口IObjectSafety.cs
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)] 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); } }
第五步:添加调用JS的接口IOleClientSite.cs,IOleContainer.cs
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace HuaYun.ActiveX { [ComImport,Guid("00000118-0000-0000-C000-000000000046"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 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(); } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace HuaYun.ActiveX { [ComImport,Guid("0000011B-0000-0000-C000-000000000046"),InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 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); } }
第六步:编写ActiveXControl.cs代码,类上的GUID很关键这个就是“Object”的“classid”
ps:<object classid="clsid:de4479a4-af99-45b0-b0ce-d72bd4c2c37d" ></object>
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 System.Reflection; using mshtml; namespace HuaYun.ActiveX { [Guid("21209360-34E1-423E-A81F-BC80B62021B7")] public partial class ActiveXControl : UserControl, IObjectSafety { public ActiveXControl() { InitializeComponent(); } #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 private void button1_Click(object sender, EventArgs e) { this.CallJavaScript("sex"); } private void ActiveXControl_Load(object sender, EventArgs e) { } // 被JS调用的ActiveX方法 public void SayHi(string msg) { MessageBox.Show(msg); } // 调用JS方法 private void CallJavaScript(string filename) { 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[1]; args[0] = filename; //获取页面的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 { } } } }
ps:以上完成了编码工作,现在要生成项目,我使用的是VS2017没有安装部署工具需要在“工具”-“扩展和更新”找到“Mircrosoft Visual Studio 2017 Installer Projects”下载安装。
补充步骤:右键工程属性,“应用程序”-“程序集信息”勾选使程序集COM可见。“生成”勾选为COM互操作注册
第七步:创建安装项目命名为“TYacticeX”,ps:右键工程顶级菜单
第八步:修改工程属性,将“RemovePreviousVers”的值设置为True
第九步:右键安装项目,“Add”-“项目输出”-“主输出”,然后输出安装文件,一个exe和一个msi
第十步:开始写对应的html代码与JS代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">
function OnScaned (filename){
document.getElementById("dx").value =filename;
}
</script>
</head>
<body>
<label for="jsCall">js call ActiveX:</label>
<button id="jsCall" onclick="csharpActiveX.SayHi('hello word');">call</button>
<br/>
<label for="dx">activeX call JS:</label>
<input name="dx" id="dx" type="text" />
<object id="csharpActiveX" classid="clsid:21209360-34E1-423E-A81F-BC80B62021B7" codebase="lib/setup.exe"
width="800" height="200" id="helloBossma">
</object>
</body>
</html>
ps:已经可以开始测试了。