TL / DR
我创建的托管C#COM可见对象有一个事件。在" OnCardRead"方法(触发实际事件)我检查事件是否订阅,它是。 javascript中的事件回调代码似乎永远不会被调用。
故事
项目很简单。创建一个"打开"一个rfid设备并返回卡的序列号。那部分有自己的单元测试,工作得很好。如果串行端口地址设置为0,以帮助我自我调试,那么它使用我的MockRfidSDK。但是为了彻底彻底,这里的代码(减去实际的RFID代码)。
IRfidDevice
[Guid("E86A9038-368D-4e8f-B389-FDEF38935B2F"), InterfaceType(ComInterfaceType.InterfaceIsDual), ComVisible(true)]
public interface IRfidDevice
{
[DispId(1)]
int Open();
[DispId(2)]
int Close();
[DispId(3)]
void SetComPort(int comport);
[DispId(4)]
void FlashLed(int led);
}
IRfidEvent
[ComVisible(true), GuidAttribute("0422D916-C11A-474e-947D-45A107038D12"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface IRfidEvent
{
[DispIdAttribute(0x60020000)]
void CardUidReceived(byte sak, ushort atq, string uid);
}
RfidSdk / EmptyRfidSdk
internal interface RfidSdk
{
void Open();
int GetCard();
byte[] SelectCard();
int Close();
void FlashLed(int led);
}
class EmptyRfidSdk : RfidSdk
{
public void Open()
{
}
public int GetCard()
{
System.Threading.Thread.Sleep(10);
return 0x0344;
}
public byte[] SelectCard()
{
System.Threading.Thread.Sleep(2000);
return new byte[] { 0x20, 0x44, 0x03, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 };
}
public int Close()
{
return 0;
}
public void FlashLed(int led)
{
}
}
RfidDevice
[Guid("873355E1-2D0D-476f-9BEF-C7E645024C32"), ProgId("MasterRDActiveX.RfidDevice"), ClassInterface(ClassInterfaceType.None), ComDefaultInterface(typeof(IRfidDevice)), ComVisible(true), ComSourceInterfaces(typeof(IRfidEvent))]
public class RfidDevice : InternetSafeObject, IRfidDevice
{
private RfidSdk sdk;
private bool _searchForCard = false;
[ComVisible(false)]
public delegate void RfidEventHandler(byte sak, ushort atq, string uid);
public event RfidEventHandler CardUidReceived;
public int Open()
{
try
{
sdk.Open();
_searchForCard = true;
Task.Factory.StartNew(SearchForCard);
return 0;
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
return -1;
}
}
public int Close()
{
try
{
_searchForCard = false;
sdk.Close();
sdk = null;
return 0;
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
return -1;
}
}
public void SetComPort(int comport)
{
if (sdk != null) Close();
if (comport < 1)
{
sdk = new EmptyRfidSdk();
}
else
{
sdk = new MasterRDWrapper.MasterRD(comport);
}
}
public void FlashLed(int led)
{
sdk.FlashLed(led);
}
private void SearchForCard()
{
while (_searchForCard)
{
int temp = 0;
while ((temp = sdk.GetCard()) == 0)
{
}
if (temp == sdk.GetCard())
{
var card = sdk.SelectCard();
FireCardUidReceived(card[0], BitConverter.ToUInt16(card, 1), card.Skip(3).ToArray());
}
}
}
private void FireCardUidReceived(byte sak, ushort atq, byte[] uid)
{
if (CardUidReceived != null)
{
Console.Beep(1000,100);
CardUidReceived(sak, atq, BitConverter.ToString(uid));
}
else
{
Console.Beep(2000, 2000);
}
}
所以代码工作得很好。记住哔哔声。短蜂鸣声表示事件已订阅,长蜂鸣声表示它未被订阅。
现在网页上的内容对我来说有点模糊。我在这里看了很多ActiveX教程是关于HTML代码的一些规则。它不能使用已弃用的HTML标记(IE ... OBJECT)。到目前为止,这是我的解决方案
rfidScript.js
function onRfidCard(a, b, c) {
console.log('I am in your event');
document.getElementById('result').innerHTML = c;
console.log('all done in your event');
}
function tryRfid(rfidDevice) {
var uidTag = document.getElementById('result');
var comPort = parseInt(document.getElementById('comPortBox').value);
if (rfidDevice != null) {
rfidDevice.SetComPort(comPort);
if (rfidDevice.Open() === 0) {
uidTag.innerHTML = "Please Tap Card";
}
else {
document.getElementById('error').innerHTML = "Failed to Open";
}
}
}
function closeRfid(rfidDevice) {
rfidDevice.Close();
}
最后一位是html代码
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>RFID ActiveX Test</title>
<!--//C:\Users\snyder\Source\Repos\xPD\MasterRDActiveX\MasterRDActiveX\bin\Debug\testRfid.html-->
<script type="text/javascript">
var ctrl = new ActiveXObject('MasterRDActiveX.RfidDevice');
eval('function ctrl::CardUidReceived(a,b,c){ onRfidCard(a,b,c); }');
</script>
<script src="rfidScript.js"></script>
</head>
<body>
<h1>This is our Active X Test Page for RFID</h1>
<input type="text" id="comPortBox" /> <br />
<button type="button" onclick="tryRfid(ctrl);">Open</button>
<button type="button" onclick="closeRfid(ctrl);">Close</button>
<h2>
<output id="error" style="color: red;"></output>
<output id="result"></output>
</h2>
</body>
</html>
我启动IE,在文本框中输入0,单击打开,我听到一声短促的哔声(只有一个......不知道为什么在那个上面,因为我希望每2秒发出一声哔声看到note1 ),但我没有看到结果输出标签中显示任何文字(我尝试使用警报无效。)为什么??????我错过了什么?
注1 - 早些时候,当我发出长长的哔哔声时,它会像我期望的那样一遍又一遍地发出哔哔声。