first commit of code to sit as service on machine, wait for card reader input, read the unique Id from the card, then post to the remote endpoint.

This commit is contained in:
chris.watts90@outlook.com 2017-01-25 22:43:41 +00:00
commit fd78367fb9
15 changed files with 584 additions and 0 deletions

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<appSettings>
<add key="DataCenterServiceEndpoint" value="http://localhost:1234"/>
</appSettings>
</configuration>

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5F30E8E4-5107-4C99-ADFF-38D735DC113D}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CardReaderService</RootNamespace>
<AssemblyName>CardReaderService</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="pcsc-sharp, Version=3.6.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\PCSC.3.6.0\lib\net40\pcsc-sharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConfigureService.cs" />
<Compile Include="DataCenterHelper.cs" />
<Compile Include="Service1.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Service1.Designer.cs">
<DependentUpon>Service1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CardReaderService", "CardReaderService.csproj", "{5F30E8E4-5107-4C99-ADFF-38D735DC113D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CardReaderServiceHost", "..\CardReaderServiceHost\CardReaderServiceHost.csproj", "{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Release|Any CPU.Build.0 = Release|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Topshelf;
namespace CardReaderService
{
internal static class ConfigureService
{
internal static void Configure()
{
HostFactory.Run(configure =>
{
configure.Service<Service1>(service =>
{
service.ConstructUsing(s => new Service1());
service.WhenStarted(s => s.Start(null));
service.WhenStopped(s => s.Stop());
});
//Setup Account that window service use to run.
configure.RunAsLocalSystem();
configure.SetServiceName("MyWindowServiceWithTopshelf");
configure.SetDisplayName("MyWindowServiceWithTopshelf");
configure.SetDescription("My .Net windows service with Topshelf");
});
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace CardReaderService
{
static class DataCenterHelper
{
public static void Post(CardDataPost postObject, string url)
{
var endpointConfig = ConfigurationManager.AppSettings["DataCenterServiceEndpoint"] ??
"http://localhost:8800";
using (var client = new HttpClient())
{
var jsonObject = JsonConvert.SerializeObject(url);
var content = new StringContent(jsonObject, Encoding.UTF8, "application/json");
var response = client.PostAsync(endpointConfig, content).Result;
}
}
public static Task PostAsync(CardDataPost postObject, string url)
{
return Task.Run(() => Post(postObject, url));
}
}
public class CardDataPost
{
public string CardUId { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Xsl;
namespace CardReaderService
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CardReaderService")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CardReaderService")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("5f30e8e4-5107-4c99-adff-38d735dc113d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,37 @@
namespace CardReaderService
{
partial class Service1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Service1";
}
#endregion
}
}

View File

@ -0,0 +1,157 @@
using PCSC;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CardReaderService
{
public partial class Service1 : ServiceBase
{
private Thread _mainWorkThread;
private bool _stopMainWorkerThread;
private string _readerName = "";
//private SCardReader _reader;
private SCardMonitor _cardMonitor;
public Service1()
{
InitializeComponent();
}
public void Start(string[] args)
{
OnStart(args);
}
protected override void OnStart(string[] args)
{
Debug.WriteLine("Starting.. Getting available readers");
var ctxFactory = ContextFactory.Instance;
using(var context = ctxFactory.Establish(SCardScope.System))
{
var readerNames = context.GetReaders();
if (NoReaderAvailable(readerNames))
{
Debug.WriteLine("No Card Reader is available, Exiting..");
return;
}
Debug.WriteLine("Choosing first available reader: " + readerNames.First());
_readerName = readerNames.First();
_cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System);
_cardMonitor.CardInserted += _cardMonitor_CardInserted;
_cardMonitor.Start(_readerName);
StartWorkerThread();
//_reader = new SCardReader(context);
//var err = _reader.Connect( _readerName,
// SCardShareMode.Shared,
// SCardProtocol.T0 | SCardProtocol.T1);
}
}
public void Stop()
{
OnStop();
}
protected override void OnStop()
{
_stopMainWorkerThread = true;
_mainWorkThread.Join(3000);
if (_mainWorkThread.IsAlive)
{
_mainWorkThread.Interrupt();
}
_cardMonitor.Cancel();
_cardMonitor.Dispose();
_cardMonitor = null;
}
private void StartWorkerThread()
{
_stopMainWorkerThread = false;
_mainWorkThread = new Thread(MainWorkerThread)
{
Name = "CardServiceMainThread",
IsBackground = false
};
_mainWorkThread.Start();
}
private void _cardMonitor_CardInserted(object sender, CardStatusEventArgs e)
{
var ctxFac = ContextFactory.Instance;
using (var ctx = ctxFac.Establish(SCardScope.System))
{
var reader = new SCardReader(ctx);
var pioSendPci = new IntPtr();
byte[] rcvBuffer = new byte[256];
if (_readerName == string.Empty)
{
Console.WriteLine("Reader name is somehow empty... WTF!");
_stopMainWorkerThread = true;
return;
}
var err = reader.Connect(_readerName, SCardShareMode.Shared, SCardProtocol.T0 | SCardProtocol.T1);
if (err == SCardError.Success)
{
var uIdcmd = new byte[] { 0xFF, 0xCA, 0x00, 0x00, 0x00 };
err = reader.Transmit(pioSendPci, uIdcmd, ref rcvBuffer);
if (err == SCardError.Success)
{
var uid = ConvertByteUIDToString(rcvBuffer);
var atrString = ConvertByteUIDToString(e.Atr);
Console.WriteLine("Card Inserted, ATR: " + atrString + ", and UID is: " + uid);
CardDataPost postObj = new CardDataPost {CardUId = uid};
DataCenterHelper.Post(postObj, "/postSwipeData");
Console.WriteLine("Posted to Server");
}
}
else
{
Console.WriteLine("Reader failed to connect, error: " + Enum.GetName(typeof(SCardError), err));
}
}
}
private void MainWorkerThread()
{
while (!_stopMainWorkerThread)
{
//dont actually need to do anything.. but cannot exit right away?
Thread.Sleep(3000);
}
}
private string ConvertByteUIDToString(byte[] uid)
{
StringBuilder sb = new StringBuilder();
foreach(var b in uid)
{
sb.AppendFormat("{0:X2}", b);
}
return sb.ToString();
}
private bool NoReaderAvailable(ICollection<string> readerNames)
{
return readerNames == null || readerNames.Count < 1;
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="PCSC" version="3.6.0" targetFramework="net452" />
</packages>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CardReaderServiceHost</RootNamespace>
<AssemblyName>CardReaderServiceHost</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\CardReaderService\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CardReaderService\CardReaderService.csproj">
<Project>{5f30e8e4-5107-4c99-adff-38d735dc113d}</Project>
<Name>CardReaderService</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CardReaderService;
namespace CardReaderServiceHost
{
class Program
{
static void Main(string[] args)
{
Service1 service1 = new Service1();
service1.Start(null);
Console.WriteLine("Service Running...");
Console.ReadLine();
service1.Stop();
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CardReaderServiceHost")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CardReaderServiceHost")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6e48913f-9d8c-4132-93a7-c7b1c6dd5264")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
</packages>