diff --git a/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs b/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs index 6f6d5d8..3ecf735 100644 --- a/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs +++ b/DataCenter_Windows/WindowsDataCenter/CardReaderService/CardReaderService.cs @@ -18,6 +18,9 @@ namespace CardReaderService private string _readerName = ""; private SCardMonitor _cardMonitor; + private bool _initialised = false; + private AutoResetEvent _mainWorkerTerminationSignal; + private ILogger _logger; public CardReaderService() @@ -32,43 +35,9 @@ namespace CardReaderService protected override void OnStart(string[] args) { - var configPath = string.Concat(System.Reflection.Assembly.GetEntryAssembly().Location, ".config"); - _logger = NinjectHelper.GetInstance().Get(); - _logger.Trace("Starting Service.. Getting available readers"); - var ctxFactory = ContextFactory.Instance; - using(var context = ctxFactory.Establish(SCardScope.System)) - { - var readerNames = context.GetReaders(); - if (NoReaderAvailable(readerNames)) - { - _logger.Trace("No Card Reader is available, Exiting.."); - throw new ApplicationException("A card reader must be provided in order to operate."); - } - foreach (var reader in readerNames) - { - _logger.Trace("Found reader: {0}", reader); - } - - var readerNameConfig = ConfigurationHandler.ConfigurationHandler.GetConfiguration("ReaderName"); - if (string.IsNullOrEmpty(readerNameConfig) || (!readerNames.Contains(readerNameConfig))) - { - _logger.Warn("No reader found with the name: {0}, defaulting to first available reader {1}", - readerNameConfig, readerNames.First()); - - readerNameConfig = readerNames.First(); - - } - _logger.Trace("Choosing reader: {0}", readerNameConfig); - _readerName = readerNameConfig; - - _cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System); - _cardMonitor.CardInserted += _cardMonitor_CardInserted; - _cardMonitor.Start(_readerName); - - StartWorkerThread(); - } + StartWorkerThread(); } public void StopService() @@ -79,6 +48,7 @@ namespace CardReaderService protected override void OnStop() { _stopMainWorkerThread = true; + _mainWorkerTerminationSignal.Set(); if (_mainWorkThread!= null && _mainWorkThread.IsAlive) { _mainWorkThread.Join(3000); @@ -102,6 +72,7 @@ namespace CardReaderService Name = "CardServiceMainThread", IsBackground = false }; + _mainWorkerTerminationSignal = new AutoResetEvent(false); _mainWorkThread.Start(); } @@ -151,7 +122,51 @@ namespace CardReaderService while (!_stopMainWorkerThread) { //dont actually need to do anything.. but cannot exit right away? - Thread.Sleep(3000); + if (!WeHaveValidCardReader()) + { + if (_initialised) + { + //card reader no longer available, tidy up. + _cardMonitor.Cancel(); + _cardMonitor.CardInserted -= _cardMonitor_CardInserted; + _cardMonitor.Dispose(); + _cardMonitor = null; + _initialised = false; + } + var ctxFactory = ContextFactory.Instance; + using (var context = ctxFactory.Establish(SCardScope.System)) + { + var readerNames = context.GetReaders(); + if (NoReaderAvailable(readerNames)) + { + _logger.Trace("No Card Reader is available.."); + } + else + { + foreach (var reader in readerNames) + { + _logger.Trace("Found reader: {0}", reader); + } + + var readerNameConfig = ConfigurationHandler.ConfigurationHandler.GetConfiguration("ReaderName"); + if (string.IsNullOrEmpty(readerNameConfig) || (!readerNames.Contains(readerNameConfig))) + { + _logger.Warn("No reader found with the name: {0}, defaulting to first available reader {1}", + readerNameConfig, readerNames.First()); + + readerNameConfig = readerNames.First(); + } + _logger.Trace("Choosing reader: {0}", readerNameConfig); + _readerName = readerNameConfig; + + _cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System); + _cardMonitor.CardInserted += _cardMonitor_CardInserted; + _cardMonitor.Start(_readerName); + _initialised = true; + } + } + } + _mainWorkerTerminationSignal.WaitOne(3000); } } @@ -169,5 +184,23 @@ namespace CardReaderService { return readerNames == null || readerNames.Count < 1; } + + private bool WeHaveValidCardReader() + { + if (_cardMonitor == null) + { + return false; + } + Console.WriteLine(_cardMonitor.GetCurrentState(0)); + if (_cardMonitor.GetCurrentState(0) == SCRState.Unknown + || _cardMonitor.GetCurrentState(0) == SCRState.Unavailable + || _cardMonitor.GetCurrentState(0) == (SCRState.Ignore | SCRState.Unavailable) + //|| _cardMonitor.GetCurrentState(0) == SCRState.Unaware //if we say this is an invalid state, we cause a memory leak where we create a duplicate card monitor, subscribe and overwrite. + ) + { + return false; + } + return true; + } } }