Skip to content

Commit

Permalink
New feature: DeviceMonitor (#40)
Browse files Browse the repository at this point in the history
* Update build & test toolset

* Update build & test toolset (NUnit,Fake,..)
* Update System.Reactive (.netstandard)
* Removed empty test project

* Cleanup example projects

* Added (native) example for #31

* Working on issue #31
- Start to implement a DeviceMonitor (to detect attached/detached readers)

* Added proposed solution from @olegsavelos (issue #31)
- DeviceMonitorFactory
- DeviceMonitor
- Rx-extensions to observe device events

* Added feature #31
  • Loading branch information
danm-de committed Nov 18, 2016
1 parent 250da97 commit f484b41
Show file tree
Hide file tree
Showing 80 changed files with 5,786 additions and 1,754 deletions.
8 changes: 5 additions & 3 deletions .paket/paket.targets
Expand Up @@ -12,12 +12,13 @@
</PropertyGroup>
<PropertyGroup>
<!-- Paket command -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND Exists('$(PaketRootPath)paket.exe')">$(PaketRootPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' ">$(PaketToolsPath)paket.exe</PaketExePath>
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' ">$(PaketToolsPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
<PaketCommand Condition=" '$(OS)' == 'Windows_NT'">"$(PaketExePath)"</PaketCommand>
<PaketCommand Condition=" '$(OS)' != 'Windows_NT' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"</PaketCommand>
<PaketBootStrapperCommand Condition=" '$(OS)' == 'Windows_NT'">"$(PaketBootStrapperExePath)" $(PaketBootStrapperCommandArgs)</PaketBootStrapperCommand>
<PaketBootStrapperCommand Condition=" '$(OS)' != 'Windows_NT' ">$(MonoPath) --runtime=v4.0.30319 $(PaketBootStrapperExePath) $(PaketBootStrapperCommandArgs)</PaketBootStrapperCommand>
<PaketBootStrapperCommand Condition=" '$(OS)' == 'Windows_NT' AND Exists('$(PaketBootStrapperExePath)')">"$(PaketBootStrapperExePath)" $(PaketBootStrapperCommandArgs)</PaketBootStrapperCommand>
<PaketBootStrapperCommand Condition=" '$(OS)' != 'Windows_NT' AND Exists('$(PaketBootStrapperExePath)')">$(MonoPath) --runtime=v4.0.30319 $(PaketBootStrapperExePath) $(PaketBootStrapperCommandArgs)</PaketBootStrapperCommand>
<!-- Commands -->
<PaketReferences Condition="!Exists('$(MSBuildProjectFullPath).paket.references')">$(MSBuildProjectDirectory)\paket.references</PaketReferences>
<PaketReferences Condition="!Exists('$(PaketReferences)')">$(MSBuildStartupDirectory)\paket.references</PaketReferences>
Expand All @@ -33,7 +34,8 @@
<MsBuild Targets="DownloadPaket" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadPaket=$(DownloadPaket)" />
</Target>
<Target Name="DownloadPaket">
<Exec Command="$(DownloadPaketCommand)" IgnoreStandardErrorWarningFormat="true" Condition=" '$(DownloadPaket)' == 'true' AND !Exists('$(PaketExePath)')" />
<Exec Command="$(DownloadPaketCommand)" IgnoreStandardErrorWarningFormat="true"
Condition=" '$(DownloadPaket)' == 'true' AND '$(DownloadPaketCommand)' != '' AND !Exists('$(PaketExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)" IgnoreStandardErrorWarningFormat="true" WorkingDirectory="$(PaketRootPath)" Condition="Exists('$(PaketReferences)')" ContinueOnError="true" />
Expand Down
6 changes: 3 additions & 3 deletions AssemblyInfo/Common.AssemblyInfo.cs
Expand Up @@ -6,6 +6,6 @@
[assembly: AssemblyCompany("")]
[assembly: AssemblyCopyright("Copyright © 2007-2016 by Daniel Mueller")]

[assembly: AssemblyVersion("3.5.3")]
[assembly: AssemblyFileVersion("3.5.3")]
[assembly: AssemblyInformationalVersion("3.5.3")]
[assembly: AssemblyVersion("3.6.0")]
[assembly: AssemblyFileVersion("3.6.0")]
[assembly: AssemblyInformationalVersion("3.6.0")]
21 changes: 16 additions & 5 deletions Changelog
Expand Up @@ -3,12 +3,23 @@ a = Major API change
b = New Feature
c = Bug fix

2016-11-16 Daniel Mueller <daniel@danm.de>
* New version 3.6.0
* Update build & test toolset (NUnit,Fake,..)
* Update System.Reactive (.netstandard)
* Added DeviceMonitor & DeviceMonitorFactory as requested in #31
Thanks to @olegsavelos for providing valid sample code in
https://github.com/danm-de/pcsc-sharp/issues/31
* IMonitorFactory: marked .Start(..) as obsolete (it encouraged
users doing bad things - it's a factory anyway, not a Starter)
* pcsc-sharp-rx: corrected observable creation (removed .Replay)

2016-11-03 Daniel Mueller <daniel@danm.de>
* New version 3.5.3
* Bugfix: https://github.com/danm-de/pcsc-sharp/issues/37
Dispose() or finalizer should not throw if SCardContext.Release()
returns ERROR_INVALID_HANDLE.
Thanks to SGN-JSE
Thanks to @SGN-JSE

2016-11-02 Daniel Mueller <daniel@danm.de>
* New version 3.5.2
Expand Down Expand Up @@ -43,17 +54,17 @@ c = Bug fix
2016-01-21 Daniel Mueller <daniel@danm.de>
* New version 3.3.1.0
* Bugfix: https://github.com/danm-de/pcsc-sharp/issues/19
Thanks to andrew7webb!
Thanks to @andrew7webb!
* Removed public IsNullOrWhiteSpace extension method for string.
* Made InvalidApduException public.
* Code cleanups.

2015-10-28 Daniel Mueller <daniel@danm.de>
* New version 3.3.0.0
* Bugfix: https://github.com/danm-de/pcsc-sharp/issues/11
Thanks to EmptySamurai!
Thanks to @EmptySamurai!
* Bugfix: https://github.com/danm-de/pcsc-sharp/issues/15
Thanks to anzun!
Thanks to @anzun!
* WARNING: API change:
SCardContext.GetReaders(), SCardContext.GetReaders(string[]) and
SCardContextGetReaderGroups() do not throw PCSCException anymore on
Expand All @@ -74,7 +85,7 @@ c = Bug fix
* New version 3.1.0.4
* Refactored SCardMonitor to be "more" thread safe
* Bugfix: https://github.com/danm-de/pcsc-sharp/pull/7
Thanks to EmptySamurai!
Thanks to @EmptySamurai!
(https://github.com/EmptySamurai)

2013-11-29 Daniel Mueller <daniel@danm.de>
Expand Down
95 changes: 59 additions & 36 deletions Examples/CardStatus/Program.cs
@@ -1,73 +1,96 @@
using System;
using System.Collections.Generic;
using PCSC;

namespace CardStatus
{
public class Program
{
static void Main()
{
using (var context = new SCardContext()) {
public static void Main() {
var contextFactory = ContextFactory.Instance;

context.Establish(SCardScope.System);

// retrieve all reader names
using (var context = contextFactory.Establish(SCardScope.System)) {
var readerNames = context.GetReaders();

if (readerNames == null || readerNames.Length < 1) {
if (NoReaderFound(readerNames)) {
Console.WriteLine("No readers found.");
Console.ReadKey();
return;
} else {
DisplayReaderStatus(context, readerNames);
}

// get the card status of each reader that is currently connected
foreach (var readerName in readerNames) {
using (var reader = new SCardReader(context)) {
Console.WriteLine("Trying to connect to reader {0}.", readerName);
Console.ReadKey();
}
}

/// <summary>
/// Displays the card status of each reader in <paramref name="readerNames"/>
/// </summary>
/// <param name="context">Smartcard context to connect</param>
/// <param name="readerNames">Smartcard readers</param>
private static void DisplayReaderStatus(ISCardContext context, IEnumerable<string> readerNames) {
foreach (var readerName in readerNames) {
using (var reader = new SCardReader(context)) {
Console.WriteLine("Trying to connect to reader {0}.", readerName);

var sc = reader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any);
if (sc == SCardError.Success) {
DisplayReaderStatus(reader);
reader.Disconnect(SCardReaderDisposition.Reset);
} else {
Console.WriteLine("No card inserted or reader is reserved exclusively by another application.");
Console.WriteLine("Error message: {0}\n", SCardHelper.StringifyError(sc));
}
var sc = reader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any);
if (sc != SCardError.Success) {
Console.WriteLine("No card inserted or reader is reserved exclusively by another application.");
Console.WriteLine("Error message: {0}\n", SCardHelper.StringifyError(sc));
continue;
}
}

Console.ReadKey();
PrintReaderStatus(reader);
Console.WriteLine();
reader.Disconnect(SCardReaderDisposition.Reset);
}
}
}

private static void DisplayReaderStatus(ISCardReader reader) {
/// <summary>
/// Queries the reader's status and prints it out
/// </summary>
/// <param name="reader">Connected reader</param>
private static void PrintReaderStatus(ISCardReader reader) {
string[] readerNames;
SCardProtocol proto;
SCardState state;
byte[] atr;

var sc = reader.Status(
out readerNames, // contains the reader name(s)
out state, // contains the current state (flags)
out proto, // contains the currently used communication protocol
out atr); // contains the ATR
out readerNames, // contains the reader name(s)
out state, // contains the current state (flags)
out proto, // contains the currently used communication protocol
out atr); // contains the ATR

if (sc == SCardError.Success) {
Console.WriteLine("Connected with protocol {0} in state {1}", proto, state);
DisplayCardAtr(atr);
Console.WriteLine();
} else {
Console.WriteLine("Unable to retrieve card status.\nError message: {0}",
if (sc != SCardError.Success) {
Console.WriteLine("Unable to retrieve card status.\nError message: {0}",
SCardHelper.StringifyError(sc));
return;
}

Console.WriteLine("Connected with protocol {0} in state {1}", proto, state);
PrintCardAtr(atr);
}

private static void DisplayCardAtr(byte[] atr) {
/// <summary>
/// Prints the smart cards ATR as hex string
/// </summary>
/// <param name="atr">ATR bytes</param>
private static void PrintCardAtr(byte[] atr) {
if (atr == null || atr.Length <= 0) {
return;
}

Console.WriteLine("Card ATR: {0}", BitConverter.ToString(atr));
}

/// <summary>
/// Returns <c>true</c> if the supplied collection <paramref name="readerNames"/> does not contain any reader name.
/// </summary>
/// <param name="readerNames">Collection of smartcard reader names</param>
/// <returns><c>true</c> if no reader found</returns>
private static bool NoReaderFound(ICollection<string> readerNames) {
return readerNames == null || readerNames.Count < 1;
}
}
}
}
71 changes: 0 additions & 71 deletions Examples/Examples.sln

This file was deleted.

6 changes: 0 additions & 6 deletions Examples/Examples.sln.DotSettings

This file was deleted.

0 comments on commit f484b41

Please sign in to comment.