C# 作为Windows服务运行时的PCSC.InvalidContextException

C# 作为Windows服务运行时的PCSC.InvalidContextException,c#,windows,service,smartcard,pcsc,C#,Windows,Service,Smartcard,Pcsc,我一直在使用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;

我一直在使用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));
        }
    }
}
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());
        }
但是,当尝试将其作为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方法的新代码如下所示:

    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));
        }
    }
}
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());
        }

希望这些信息能帮助其他人解决问题。

我设法解决了这个问题-问题已更新以反映变化。

Hii Jayse这对我不起作用,我已使用删除,但仍然存在错误