C# ActiveX开发及安装部署

  最近项目中,因为需要在WEB页面上操作串口,包括串口查询、打开、发送指令、接收数据、关闭串口等功能。如下所示:

  考虑使用ActiveX来实现。因为以前没有这方面的经验,开发过程中也是遇到各种问题。废话不多说,下面进入正题:

  1:打开VS2008,新建项目,以下是具体代码:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Windows.Forms;
  4 using System.IO.Ports;
  5 using System.IO;
  6 using System.Reflection;
  7 using System.Runtime.InteropServices;
  8 using mshtml;
  9 using System.Text;
 10 using Microsoft.Win32;
 11 using System.Threading;
 12 
 13 namespace WebSerial
 14 {
 15     [ProgId("WebSerial")]//控件名称
 16     [ClassInterface(ClassInterfaceType.AutoDual), ComSourceInterfaces(typeof(ControlEvents))]
 17     [Guid("6C6A0DE4-193A-48f5-BA91-3C180558785B")]//控件的GUID,用于COM注册和HTML中Object对象classid引用
 18     [ComVisible(true)]
 19     public partial class SerialPortControl : UserControl,IObjectSafety
 20     {
 21         ExSerialPort serialPort;
 22         List%26lt;byte%26gt; buffer = new List%26lt;byte%26gt;(4096);
 23 
 24         /// %26lt;summary%26gt;
 25         /// 是否准备关闭串口
 26         /// %26lt;/summary%26gt;
 27         private static bool m_IsTryToClosePort = false;
 28         /// %26lt;summary%26gt;
 29         /// 是否正在接收数据
 30         /// %26lt;/summary%26gt;
 31         private static bool m_IsReceiving = false;
 32         public SerialPortControl()
 33         {
 34 
 35         }
 36 
 37         /// %26lt;summary%26gt;
 38         /// 获取本地串口列表,以逗号隔开
 39         /// %26lt;/summary%26gt;
 40         /// %26lt;returns%26gt;%26lt;/returns%26gt;
 41         public string getComPorts()
 42         {
 43             string ports = "";
 44             foreach (string s in ExSerialPort.GetPortNames())
 45             {
 46                 ports += "," + s;
 47             }
 48             return ports.Length %26gt; 0 ? ports.Substring(1) : "";
 49         }
 50 
 51         /// %26lt;summary%26gt;
 52         /// 以指定串口号和波特率连接串口
 53         /// %26lt;/summary%26gt;
 54         /// %26lt;param name="com"%26gt;端口号%26lt;/param%26gt;
 55         /// %26lt;param name="baudRate"%26gt;波特率%26lt;/param%26gt;
 56         /// %26lt;returns%26gt;%26lt;/returns%26gt;
 57         [ComVisible(true)]
 58         public string connect(string com, int baudRate)
 59         {
 60             close();
 61             serialPort = null;
 62             serialPort = new ExSerialPort(com);
 63             serialPort.BaudRate = baudRate;
 64             serialPort.Parity = Parity.None;
 65             serialPort.DataBits = 8;
 66             serialPort.Encoding = Encoding.ASCII;
 67             serialPort.ReceivedBytesThreshold = 5;
 68             serialPort.ReadBufferSize = 102400;
 69 
 70             try
 71             {
 72                 serialPort.Open();
 73                 if (serialPort.IsOpen)
 74                 {
 75                     m_IsTryToClosePort = false;
 76                     this.clear();
 77                     serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
 78                     return "true";
 79                 }
 80             }
 81             catch { }
 82 
 83             return "false";
 84         }
 85 
 86         /// %26lt;summary%26gt;
 87         /// 清理串口数据并关闭串口
 88         /// %26lt;/summary%26gt;
 89         [ComVisible(true)]
 90         public void close()
 91         {
 92             m_IsTryToClosePort = true;
 93             while (m_IsReceiving)
 94             {
 95                 Application.DoEvents();
 96             }
 97 
 98             if (serialPort != null)
 99             {
100                 serialPort.Dispose();
101             }
102         }
103 
104         /// %26lt;summary%26gt;
105         /// 清理串口数据
106         /// %26lt;/summary%26gt;
107         [ComVisible(true)]
108         public void clear()
109         {
110             if (serialPort != null %26amp;%26amp; serialPort.IsOpen)
111             {
112                 serialPort.Clear();
113             }
114         }
115 
116         /// %26lt;summary%26gt;
117         /// 发送字符串
118         /// %26lt;/summary%26gt;
119         /// %26lt;param name="s"%26gt;%26lt;/param%26gt;
120         [ComVisible(true)]
121         public void writeString(string hexString)
122         {
123             if (serialPort != null %26amp;%26amp; serialPort.IsOpen)
124             {
125                 byte[] bytes = strToToHexByte(hexString);
126                 serialPort.Write(bytes, 0, bytes.Length);
127             }
128         }
129 
130         /// %26lt;summary%26gt;
131         /// 字符串转16进制字节数组
132         /// %26lt;/summary%26gt;
133         /// %26lt;param name="hexString"%26gt;%26lt;/param%26gt;
134         /// %26lt;returns%26gt;%26lt;/returns%26gt;
135         private static byte[] strToToHexByte(string hexString)
136         {
137             hexString = hexString.Replace(" ", "");
138             if ((hexString.Length % 2) != 0)
139                 hexString += " ";
140             byte[] returnBytes = new byte[hexString.Length / 2];
141             for (int i = 0; i %26lt; returnBytes.Length; i++)
142                 returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
143             return returnBytes;
144         }
145 
146         ///  %26lt;summary%26gt;  
147         /// 字节数组转字符串16进制  
148         ///  %26lt;/summary%26gt;  
149         ///  %26lt;param name="InBytes"%26gt; 二进制字节 %26lt;/param%26gt;  
150         ///  %26lt;returns%26gt;类似"01 02 0F" %26lt;/returns%26gt;  
151         public static string ByteToString(byte[] InBytes)
152         {
153             string StringOut = "";
154             foreach (byte InByte in InBytes)
155             {
156                 //StringOut += String.Format("{0:X2}", InByte) + " ";  
157                 StringOut += " " + InByte.ToString("X").PadLeft(2, '0');
158             }
159 
160             return StringOut.Trim();
161         }
162 
163         /// %26lt;summary%26gt;
164         /// 接收数据
165         /// %26lt;/summary%26gt;
166         /// %26lt;param name="sender"%26gt;%26lt;/param%26gt;
167         /// %26lt;param name="e"%26gt;%26lt;/param%26gt;
168         void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
169         {
170             if (m_IsTryToClosePort)
171             {
172                 return;
173             }
174 
175             m_IsReceiving = true;
176 
177             try
178             {
179                 int n = serialPort.BytesToRead;
180                 if (n %26gt; 0)
181                 {
182                     byte[] buf = new byte[n];
183                     serialPort.Read(buf, 0, n);
184                     string dataString = ByteToString(buf);
185                     Receive(dataString);
186                 }
187 
188                 ////1.缓存数据
189                 //buffer.AddRange(buf);
190                 ////2.完整性判断
191                 //while (buffer.Count %26gt;= 5) //至少包含帧头(2字节)、长度(1字节)、校验位(1字节);根据设计不同而不同
192                 //{
193                 //    //2.1 查找数据头
194                 //    if (buffer[0] == 0xff %26amp;%26amp; buffer[1] == 0x55) //传输数据有帧头,用于判断
195                 //    {
196                 //        int len = buffer[2];
197                 //        if (buffer.Count %26lt; len + 4) //数据区尚未接收完整
198                 //        {
199                 //            break;
200                 //        }
201                 //        //得到完整的数据,复制到ReceiveBytes中进行校验
202                 //        byte[] ReceiveBytes = new byte[len + 4];
203                 //        buffer.CopyTo(0, ReceiveBytes, 0, len + 4);
204 
205                 //        byte checkByte = ReceiveBytes[len + 3];//获取校验字节
206                 //        byte realCheckByte = 0x00;
207                 //        realCheckByte -= buffer[2];
208                 //        for (int packIndex = 0; packIndex %26lt; len; packIndex++)//将后面的数据加起来
209                 //        {
210                 //            realCheckByte -= ReceiveBytes[packIndex + 3];
211                 //        }
212 
213                 //        if (checkByte == realCheckByte)//验证,看数据是否合格
214                 //        {
215                 //            string dataString = ByteToString(ReceiveBytes);                            
216                 //            Receive(dataString);
217                 //        }
218                 //        buffer.RemoveRange(0, len + 4);
219                 //    }
220                 //    else //帧头不正确时,清除
221                 //    {
222                 //        buffer.RemoveAt(0);
223                 //    }
224 
225                 //}
226             }
227             finally
228             {
229                 m_IsReceiving = false;
230             }
231         }
232 
233         public event ControlEventHandler OnReceive;
234         [ComVisible(true)]
235         private void Receive(string dataString)
236         {
237             if (OnReceive != null)
238             {
239                 OnReceive(dataString); //Calling event that will be catched in JS
240             }
241         }
242 
243         ///    %26lt;summary%26gt;
244         ///    Register the class as a    control    and    set    it's CodeBase entry
245         ///    %26lt;/summary%26gt;
246         ///    %26lt;param name="key"%26gt;The registry key of the control%26lt;/param%26gt;
247         [ComRegisterFunction()]
248         public static void RegisterClass(string key)
249         {
250             // Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
251             StringBuilder sb = new StringBuilder(key);
252 
253             sb.Replace(@"HKEY_CLASSES_ROOT\", "");
254             // Open the CLSID\{guid} key for write access
255             RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
256 
257             // And create    the    'Control' key -    this allows    it to show up in
258             // the ActiveX control container
259             RegistryKey ctrl = k.CreateSubKey("Control");
260             ctrl.Close();
261 
262             // Next create the CodeBase entry    - needed if    not    string named and GACced.
263             RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
264             inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
265             inprocServer32.Close();
266             // Finally close the main    key
267             k.Close();
268             MessageBox.Show("Registered");
269         }
270 
271         ///    %26lt;summary%26gt;
272         ///    Called to unregister the control
273         ///    %26lt;/summary%26gt;
274         ///    %26lt;param name="key"%26gt;Tke registry key%26lt;/param%26gt;
275         [ComUnregisterFunction()]
276         public static void UnregisterClass(string key)
277         {
278             StringBuilder sb = new StringBuilder(key);
279             sb.Replace(@"HKEY_CLASSES_ROOT\", "");
280 
281             // Open    HKCR\CLSID\{guid} for write    access
282             RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
283 
284             // Delete the 'Control'    key, but don't throw an    exception if it    does not exist
285             k.DeleteSubKey("Control", false);
286 
287             // Next    open up    InprocServer32
288             //RegistryKey    inprocServer32 = 
289             k.OpenSubKey("InprocServer32", true);
290 
291             // And delete the CodeBase key,    again not throwing if missing
292             k.DeleteSubKey("CodeBase", false);
293 
294             // Finally close the main key
295             k.Close();
296             MessageBox.Show("UnRegistered");
297         }
298 
299         #region IObjectSafety 成员
300         public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
301         {
302             pdwSupportedOptions = 1;
303             pdwEnabledOptions = 2;
304         }
305         public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
306         {
307             throw new NotImplementedException();
308         }
309         #endregion
310 
311         #region IObjectSafety 成员
312 
313         private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
314         private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
315         private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
316         private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
317         private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
318 
319         private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
320         private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
321         private const int S_OK = 0;
322         private const int E_FAIL = unchecked((int)0x80004005);
323         private const int E_NOINTERFACE = unchecked((int)0x80004002);
324 
325         private bool _fSafeForScripting = true;
326         private bool _fSafeForInitializing = true;
327 
328 
329         public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
330         {
331             int Rslt = E_FAIL;
332 
333             string strGUID = riid.ToString("B");
334             pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
335             switch (strGUID)
336             {
337                 case _IID_IDispatch:
338                 case _IID_IDispatchEx:
339                     Rslt = S_OK;
340                     pdwEnabledOptions = 0;
341                     if (_fSafeForScripting == true)
342                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
343                     break;
344                 case _IID_IPersistStorage:
345                 case _IID_IPersistStream:
346                 case _IID_IPersistPropertyBag:
347                     Rslt = S_OK;
348                     pdwEnabledOptions = 0;
349                     if (_fSafeForInitializing == true)
350                         pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
351                     break;
352                 default:
353                     Rslt = E_NOINTERFACE;
354                     break;
355             }
356 
357             return Rslt;
358         }
359 
360         public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
361         {
362             int Rslt = E_FAIL;
363 
364             string strGUID = riid.ToString("B");
365             switch (strGUID)
366             {
367                 case _IID_IDispatch:
368                 case _IID_IDispatchEx:
369                     if (((dwEnabledOptions %26amp; dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) %26amp;%26amp;
370                          (_fSafeForScripting == true))
371                         Rslt = S_OK;
372                     break;
373                 case _IID_IPersistStorage:
374                 case _IID_IPersistStream:
375                 case _IID_IPersistPropertyBag:
376                     if (((dwEnabledOptions %26amp; dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) %26amp;%26amp;
377                          (_fSafeForInitializing == true))
378                         Rslt = S_OK;
379                     break;
380                 default:
381                     Rslt = E_NOINTERFACE;
382                     break;
383             }
384 
385             return Rslt;
386         }
387 
388         #endregion
389     }
390 
391     /// %26lt;summary%26gt;
392     /// Event handler for events that will be visible from JavaScript
393     /// %26lt;/summary%26gt;
394     public delegate void ControlEventHandler(string dataString);
395 
396     /// %26lt;summary%26gt;
397     /// This interface shows events to javascript
398     /// %26lt;/summary%26gt;
399     [Guid("68BD4E0D-D7BC-4cf6-BEB7-CAB950161E79")]
400     [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
401     public interface ControlEvents
402     {
403         //Add a DispIdAttribute to any members in the source interface to specify the COM DispId.
404         [DispId(0x60020001)]
405         void OnReceive(string dataString); //This method will be visible from JS
406     }
407 
408     public class ExSerialPort : SerialPort
409     {
410         public ExSerialPort(string name)
411             : base(name)
412         {
413         }
414 
415         public void Clear()
416         {
417             try
418             {
419                 if (this.IsOpen)
420                 {
421                     this.DiscardInBuffer();
422                     this.DiscardOutBuffer();
423                 }
424             }
425             catch { }
426         }
427 
428         protected override void Dispose(bool disposing)
429         {
430             Clear();
431 
432             var stream = (Stream)typeof(SerialPort).GetField("internalSerialStream", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);
433 
434             if (stream != null)
435             {
436                 stream.Dispose();
437             }
438 
439             base.Dispose(disposing);
440         }
441     }
442 }
View Code

  2:新建安装项目,将上面项目DLL打包生成Msi安装文件。这里不多说,网上大把文章教你怎么做。

  3:新建Web项目,具体代码如下:

  1 %26lt;html%26gt; 
  2 %26lt;head%26gt; 
  3 %26lt;title%26gt;JavaScript串口测试%26lt;/title%26gt;
  4 %26lt;meta http-equiv="Content-Type" content="text/html; charset=GB2312" /%26gt;
  5 %26lt;script   language="javascript"   type="text/javascript"%26gt; 
  6 %26lt;!-- 
  7     function getComPorts()
  8     {
  9         var ports = webSerial.getComPorts();
 10         var arr = ports.split(',');
 11         var ctl = document.getElementById("ComName"); 
 12         if(ctl) 
 13         { 
 14             ctl.options.length = 0;
 15             for(var i=0;i%26lt;arr.length;i++)
 16             {
 17                 ctl.options[i] = new Option(arr[i],arr[i]); 
 18             }
 19         } 
 20    }
 21     
 22     function connectComPort()
 23     {
 24         var com = document.getElementById("ComName").value.toString();
 25         var baudRate = document.getElementById("BaudRate").value;
 26         var result = webSerial.connect(com,baudRate);
 27         alert(result);
 28     }
 29     
 30     function clearComPort()
 31     {
 32         webSerial.clear();
 33         alert("清理串口成功!");
 34     }
 35     
 36     function closeComPort()
 37     {
 38         webSerial.close();
 39         alert("关闭串口成功!");
 40     }
 41     
 42     function writeString()
 43     {
 44         var hexString = document.getElementById("txtSend").value.toString(); 
 45         webSerial.writeString(hexString);
 46         alert("发送指令成功!");
 47     } 
 48     
 49     function clearSend()
 50     {
 51         document.getElementById("txtSend").innerText="";
 52     }
 53     
 54     function clearReceive()
 55     {
 56         document.getElementById("txtReceive").innerText="";
 57     }
 58     
 59     function startTime()
 60     {
 61         var today=new Date()
 62         var h=today.getHours()
 63         var m=today.getMinutes()
 64         var s=today.getSeconds()
 65         // add a zero in front of numbers%26lt;10
 66         m=checkTime(m)
 67         s=checkTime(s)
 68         document.getElementById('lblTime').innerHTML=h+":"+m+":"+s
 69         t=setTimeout('startTime()',500)
 70     }
 71 
 72     function checkTime(i)
 73     {
 74         if (i%26lt;10) 
 75           {i="0" + i}
 76           return i
 77     }
 78 
 79 --%26gt; 
 80 %26lt;/script%26gt;   
 81 
 82 %26lt;/head%26gt; 
 83 %26lt;body οnlοad="startTime()" οnunlοad="closeComPort()"%26gt;
 84 %26lt;form name="form1"%26gt;     
 85 %26lt;fieldset style="width:225px;height:180px;text-align:center;"%26gt;
 86    %26lt;legend%26gt;串口%26lt;/legend%26gt;
 87    %26lt;div style="float:left;width:250px"%26gt;   
 88        %26lt;br/%26gt;   
 89        %26lt;span%26gt;串口号:%26lt;/span%26gt;
 90        %26lt;select name="ComName" id="ComName" style="width:100px" %26gt;  
 91        %26lt;/select%26gt;
 92        %26lt;br/%26gt;   
 93        %26lt;span%26gt;波特率:%26lt;/span%26gt;
 94    %26lt;select name="BaudRate" id="BaudRate" style="width:100px" %26gt;
 95    %26lt;option value="9600" selected="selected"%26gt;9600%26lt;/option%26gt;
 96    %26lt;option value="57600"  %26gt;57600%26lt;/option%26gt;
 97    %26lt;option value="115200" %26gt;115200%26lt;/option%26gt;   
 98    %26lt;option value="1382400" %26gt;1382400%26lt;/option%26gt;  
 99    %26lt;option value="3000000" %26gt;3000000%26lt;/option%26gt;  
100    %26lt;/select%26gt;   
101    %26lt;br/%26gt;
102        %26lt;br/%26gt;
103        %26lt;input   type="button" id="btnGetPort" style="width:80px;height:30px;font-size:13px"   name="btnGetPort"   value="获取串口"   οnclick="getComPorts()"/%26gt;       
104        %26lt;input   type="button" id="btnOpenPort" style="width:80px;height:30px;font-size:13px"   name="btnOpenPort"   value="打开串口"   οnclick="connectComPort()"/%26gt;     
105        %26lt;input   type="button" id="btnClearPort" style="width:80px;height:30px;font-size:13px"   name="btnClearPort"   value="清理串口"   οnclick="clearComPort()"/%26gt;         
106        %26lt;input   type="button" id="btnClosePort" style="width:80px;height:30px;font-size:13px"   name="btnClosePort"   value="关闭串口"   οnclick="closeComPort()"/%26gt;       
107     %26lt;/div%26gt; 
108 %26lt;/fieldset%26gt;
109 %26lt;br /%26gt;%26lt;br /%26gt;
110 %26lt;fieldset style="width:800px;height:150px;text-align:center;"%26gt;
111    %26lt;legend%26gt;发送区域%26lt;/legend%26gt;
112    %26lt;div align="left"%26gt;V6-握手指令: FF 55 01 01 FE%26lt;/div%26gt;
113    %26lt;div align="left"%26gt;V6-50HZ采集:FF 55 05 03 20 4E 00 00 8A%26lt;/div%26gt;
114    %26lt;div align="left"%26gt;V6-停止指令: FF 55 01 10 EF%26lt;/div%26gt;
115    %26lt;div style="float:left;"%26gt;
116        %26lt;textarea id="txtSend"  name="txtSend" style="width:800px;height:80px"%26gt;%26lt;/textarea%26gt; 
117        %26lt;br/%26gt;
118        %26lt;input   type="button" id="btnSend" style="width:100px;height:30px"   name="btnSend"   value="发送"   οnclick="writeString()"/%26gt;   
119        %26lt;input  type="button" id="btnClearSend" style="width:100px;height:30px"   name="btnClearSend"   value="清空"   οnclick="clearSend()"/%26gt;
120    %26lt;/div%26gt; 
121 %26lt;/fieldset%26gt;
122 %26lt;br /%26gt;%26lt;br /%26gt;
123 %26lt;fieldset style="width:800px;height:500px;text-align:center;"%26gt;
124    %26lt;legend%26gt;接收区域%26lt;/legend%26gt;   
125    %26lt;div style="float:left;"%26gt;
126    %26lt;textarea id="txtReceive"  readonly="readonly" name="txtReceive" style="width:800px;height:430px"%26gt;%26lt;/textarea%26gt;  
127    %26lt;br/%26gt;
128    %26lt;input  type="button" id="btnClearReceive" style="width:100px;height:30px"   name="btnClearReceive"   value="清空"   οnclick="clearReceive()"/%26gt;
129    %26lt;/div%26gt;
130 %26lt;/fieldset%26gt;   
131 %26lt;span id="lblTime"%26gt;%26lt;/span%26gt;
132 %26lt;/form%26gt; 
133 
134 %26lt;p%26gt;
135 
136 %26lt;object classid="clsid:6C6A0DE4-193A-48f5-BA91-3C180558785B" codebase="../WebSerialSetup.msi" width="442" height="87" id="webSerial" name="webSerial"%26gt;
137         %26lt;/object%26gt;
138 %26lt;/p%26gt;
139 
140  %26lt;!-- Attaching to an ActiveX event--%26gt;
141 %26lt;script language="javascript" type="text/javascript"%26gt;
142     function webSerial::OnReceive(dataString)
143     {
144         document.getElementById("txtReceive").value += dataString+"\r\n";;   
145     }
146 %26lt;/script%26gt;
147 %26lt;/body%26gt; 
148 %26lt;/html%26gt;  
View Code

%26nbsp; %26nbsp; %26nbsp; 在使用JS调用ActiveX的时候碰上问题一:方法可以成功调用,而事件却调用失败。网上文章大都是说JS如何调ActiveX,而ActiveX这边的方法或者事件需要满足什么条件才能被JS成功调用却少有涉及。正当我山穷水尽疑无路的时候,事情有了转折,无意中看到一篇老外写的文章。链接地址是:http://www.codeproject.com/Articles/24089/Create-ActiveX-in-NET-Step-by-Step。才知道事件需要实现一个接口才能被JS识别。所以这部分代码后面被加上去了:

  

/// %26lt;summary%26gt;
    /// Event handler for events that will be visible from JavaScript
    /// %26lt;/summary%26gt;
    public delegate void ControlEventHandler(string dataString);

    /// %26lt;summary%26gt;
    /// This interface shows events to javascript
    /// %26lt;/summary%26gt;
    [Guid("68BD4E0D-D7BC-4cf6-BEB7-CAB950161E79")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface ControlEvents
    {
        //Add a DispIdAttribute to any members in the source interface to specify the COM DispId.
        [DispId(0x60020001)]
        void OnReceive(string dataString); //This method will be visible from JS
    }

  控件类名前面也加上这个

  

[ClassInterface(ClassInterfaceType.AutoDual), ComSourceInterfaces(typeof(ControlEvents))]

  事件定义如下:

  

public event ControlEventHandler OnReceive;
        [ComVisible(true)]
        private void Receive(string dataString)
        {
            if (OnReceive != null)
            {
                OnReceive(dataString); //Calling event that will be catched in JS
            }
        }

  本地打开网页,执行全部功能,操作正常,大功告成!!!

%26nbsp;

  随后我把网页在本地发布并使用局域网中其他电脑(操作系统WIN7)IE访问该网页。那么问题来了:

  1:机器弹出对话框拒绝安装当前ActiveX。经过对IE internet选项设置,放开对无签名ActiveX访问限制后。有的机器能弹出安装对话框,有的机器仍然坚决禁止。而且就算是弹出安装对话框,在确认安装后,对话框消失,插件也没装上。。。

  好吧,这个问题也是没搞明白啥原因。后面时间紧迫,只好给客户一个下载链接,自己去点击下载。

  2:下载安装包并安装完毕后,在客户机器上操作网页功能。前面几个按钮功能都OK,但是在填入指令点击发送,网页出现崩溃重新刷新的情况,而且换了几台机器都是这样。后面想起在生成安装包的时候,有弹出一个对话框,提示Visual Studio registry capture utility 已停止工作。百度一番后,找到解决方法:在Microsoft%26nbsp;Visual%26nbsp;Studio%26nbsp;9.0/Common7/Tools/Deployment%26nbsp;路径下面的regcap.exe文件,点击右键在属性页面中,选择兼容性页面,选中%26ldquo;以兼容模式运行%26rdquo;框就好了。兼容win7%26nbsp;就行。

相应设置后,重新生成安装文件。。。在客户机上安装后,一切正常!!!

  







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值