作为Windows服务运行时,PCSC.InvalidContextException
作者:互联网
我一直在使用pcsc-sharp库开发小型智能卡扫描仪应用程序.当作为控制台应用程序运行时,该应用程序运行良好,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Drawing.Printing;
using System.Net;
using System.Net.Sockets;
using System.Data.SqlClient;
using System.Threading;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Speech.Synthesis;
using System.Diagnostics;
using PCSC;
using System.Media;
namespace MeterTestingApplication
{
class Program
{
static void Main(string[] args)
{
// Retrieve the names of all installed readers.
string[] readerNames;
using (var context = new SCardContext())
{
context.Establish(SCardScope.System);
readerNames = context.GetReaders();
context.Release();
}
if (readerNames == null || readerNames.Length == 0)
{
Console.WriteLine("There are currently no readers installed.");
return;
}
// Create a monitor object with its own PC/SC context.
// The context will be released after monitor.Dispose()
using (var monitor = new SCardMonitor(new SCardContext(), SCardScope.System))
{
// Point the callback function(s) to the anonymous & static defined methods below.
monitor.CardInserted += (sender, args0) => DisplayEvent("CardInserted", args0);
//monitor.CardRemoved += (sender, args0) => DisplayEvent("CardRemoved", args0);
//monitor.Initialized += (sender, args0) => DisplayEvent("Initialized", args0);
//monitor.StatusChanged += StatusChanged;
monitor.MonitorException += MonitorException;
monitor.Start(readerNames);
// Keep the window open
Console.ReadLine();
}
}
private static void DisplayEvent(string eventName, CardStatusEventArgs unknown)
{
Console.WriteLine(">> {0} Event for reader: {1}", eventName, unknown.ReaderName);
Console.WriteLine("ATR: {0}", BitConverter.ToString(unknown.Atr ?? new byte[0]));
Console.WriteLine("State: {0}\n", unknown.State);
//Works fine here
}
private static void StatusChanged(object sender, StatusChangeEventArgs args)
{
//Console.WriteLine(">> StatusChanged Event for reader: {0}", args.ReaderName);
//Console.WriteLine("ATR: {0}", BitConverter.ToString(args.Atr ?? new byte[0]));
//Console.WriteLine("Last state: {0}\nNew state: {1}\n", args.LastState, args.NewState);
}
private static void MonitorException(object sender, PCSCException ex)
{
Console.WriteLine("Monitor exited due an error:");
Console.WriteLine(SCardHelper.StringifyError(ex.SCardError));
}
}
}
但是,当尝试将其作为Windows服务运行时(允许扫描卡来更新数据库),该事件永远不会触发,并且在启动该服务时似乎崩溃.事件日志显示PCSC.InvalidContextException错误.该服务的代码几乎足够相同,但这是示例.
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Timers;
using System.Configuration;
using System.Linq;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Drawing.Printing;
using System.Threading;
using System.Speech.Synthesis;
using System.IO.Ports;
using System.Text.RegularExpressions;
using PCSC;
using System.Media;
using log4net;
namespace CardScannerService
{
public partial class CardScanner : ServiceBase
{
private ILog logger;
private SCardContext context;
private string[] readerNames;
private SCardMonitor monitor;
private static System.Timers.Timer aTimer;
public CardScanner()
{
InitializeComponent();
}
static void Main()
{
ServiceBase.Run(new CardScanner());
}
//
// Start Service
//
protected override void OnStart(string[] args)
{
aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = (1000 * 60 * 60 * 24); // Once a day; 1000ms * 60s * 60m * 24h
aTimer.Enabled = true;
//// Entry point
using (context = new SCardContext())
{
context.Establish(SCardScope.System);
readerNames = context.GetReaders();
context.Release();
}
if (readerNames == null || readerNames.Length == 0)
{
EventLog.WriteEntry("CardReaderService", "There are currently no readers installed.");
return;
}
// Create a monitor object with its own PC/SC context.
// The context will be released after monitor.Dispose()
using (monitor = new SCardMonitor(new SCardContext(), SCardScope.System))
{
// Point the callback function(s) to the anonymous & static defined methods below.
monitor.CardInserted += (sender, args0) => DisplayEvent("CardInserted", args0);
//monitor.CardRemoved += (sender, args0) => DisplayEvent("CardRemoved", args0);
//monitor.Initialized += (sender, args0) => DisplayEvent("Initialized", args0);
//monitor.StatusChanged += StatusChanged;
monitor.MonitorException += MonitorException;
monitor.Start(readerNames);
// Keep the window open
//Console.ReadLine();
}
logger.InfoFormat("CardScannerService Started at {0}", DateTime.Now.ToLongTimeString());
}
//
// Stop Service
//
protected override void OnStop()
{
logger.InfoFormat("CardScannerService Stopped at {0}", DateTime.Now.ToLongTimeString());
}
//
// Execute timed event every hour and half hour
//
void OnTimedEvent(object source, ElapsedEventArgs e)
{
// Card scanner service entry point for timed event - any cleanup code can go here
}
private static void DisplayEvent(string eventName, CardStatusEventArgs unknown)
{
EventLog.WriteEntry("CardReaderService", ">> " + eventName + "v Event for Reader: " + unknown.ReaderName);
EventLog.WriteEntry("CardReaderService", "ATR: " + BitConverter.ToString(unknown.Atr ?? new byte[0]));
EventLog.WriteEntry("CardReaderService", "State: " + unknown.State);
//Not firing
}
private static void StatusChanged(object sender, StatusChangeEventArgs args)
{
//Console.WriteLine(">> StatusChanged Event for reader: {0}", args.ReaderName);
//Console.WriteLine("ATR: {0}", BitConverter.ToString(args.Atr ?? new byte[0]));
//Console.WriteLine("Last state: {0}\nNew state: {1}\n", args.LastState, args.NewState);
}
private static void MonitorException(object sender, PCSCException ex)
{
EventLog.WriteEntry("CardReaderService", "Monitor exited due an error:");
EventLog.WriteEntry("CardReaderService", SCardHelper.StringifyError(ex.SCardError));
}
}
}
我已经去除了实际的数据库逻辑,因为它似乎可以正常工作,我认为在尝试释放上下文变量或将监视器附加到智能卡时,它崩溃了.
还必须指出,如果是某种访问权限错误,我尝试将服务从开始使用本地系统帐户更改为使用本地服务.
如果有人可以阐明我要去哪里,我将非常感谢您的帮助.我是接触PC / SC的新手,目前似乎对这个项目感到困惑.
更新
我现在已经解决了这个问题;事实证明Windows服务不喜欢使用语句.变量放置在块的末尾,因此上下文变得无效.
注释掉了using块,并在其位置完成了变量的声明. OnStart方法的新代码如下:
protected override void OnStart(string[] args)
{
logger = LogManager.GetLogger(this.GetType().Name);
aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = (1000 * 60 * 60 * 24); // Once a day; 1000ms * 60s * 60m * 24h
aTimer.Enabled = true;
// Entry point
//using (context = new SCardContext())
//{
context = new SCardContext();
context.Establish(SCardScope.System);
readerNames = context.GetReaders();
context.Release();
//}
if (readerNames == null || readerNames.Length == 0)
{
EventLog.WriteEntry("CardReaderService", "There are currently no readers installed.");
return;
}
// Create a monitor object with its own PC/SC context.
// The context will be released after monitor.Dispose()
//using (monitor = new SCardMonitor(new SCardContext(), SCardScope.System))
//{
monitor = new SCardMonitor(new SCardContext(), SCardScope.System);
// Point the callback function(s) to the anonymous & static defined methods below.
monitor.CardInserted += (sender, args0) => DisplayEvent("CardInserted", args0);
//monitor.CardRemoved += (sender, args0) => DisplayEvent("CardRemoved", args0);
//monitor.Initialized += (sender, args0) => DisplayEvent("Initialized", args0);
//monitor.StatusChanged += StatusChanged;
monitor.MonitorException += MonitorException;
monitor.Start(readerNames);
// Keep the window open
//Console.ReadLine();
//}
logger.InfoFormat("CardScannerService Started at {0}", DateTime.Now.ToLongTimeString());
}
希望这些信息可以帮助其他人.
解决方法:
我设法解决了这个问题-该问题已更新以反映所做的更改.
标签:smartcard,pcsc,windows,c,service 来源: https://codeday.me/bug/20191121/2049860.html