• 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 = 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

    以下为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[1];
    
                args[0] = 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打包工具

        自签名证书工具

  • 相关阅读:
    今日总结
    微任务与宏任务
    20171128微信小程序
    20171128-微信小程序之点餐
    git
    第二次学习Javascript笔记
    base64图片
    网页布局基础-css版
    StuQ技能图谱——前端
    前端开发工具
  • 原文地址:https://www.cnblogs.com/dreamcat/p/7483053.html
Copyright © 2020-2023  润新知