2014-10-07 141 views
3

我一直在使用pcsc-sharp庫的小型智能卡掃描程序應用程序。作爲控制檯應用程序運行時,應用程序正常工作,代碼如下:PCSC.InvalidContextException作爲Windows服務運行時

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合作方面相對較新,現在似乎已經在這個項目中遇到了困難。

UPDATE

我現在已經解決了這個問題;原來Windows服務不喜歡使用語句。變量放置在塊的末尾,因此上下文變得無效。

使用塊已被註釋掉,變量的聲明是在它們的位置完成的。 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()); 
     } 

希望此信息可以幫助其他人。

+0

嗨Jayse它不適合我,我刪除使用,但仍ame錯誤 – 2017-05-03 10:04:42

回答

3

我設法解決了這個問題 - 問題已更新以反映更改。

相關問題