Environment
- Windows 10
- Visual Studio 2019 Community 2019 16.8.3
- .net 5.0
image
Code
Form1.cs
using System;
using System.Text;
using System.Windows.Forms;
using PCSC;
using PCSC.Exceptions;
using PCSC.Iso7816;
using PCSC.Monitoring;
namespace PasoriForm {
public partial class Form1 : Form {
// fields
private string readerName;
private ISCardContext context;
private ISCardMonitor monitor;
// constructor
public Form1() {
InitializeComponent();
InitializePasori();
}
// pasori init
private void InitializePasori() {
try {
// check connection
context = ContextFactory.Instance.Establish(SCardScope.System);
var readerNames = context.GetReaders();
if(readerNames.Length < 1) {
throw new NoServiceException(SCardError.NoReadersAvailable); // Cannot find a smart card reader.
}
readerName = readerNames[0];
// create monitor
monitor = MonitorFactory.Instance.Create(SCardScope.System);
monitor.CardInserted += Monitor_CardInserted;
monitor.Start(readerName);
textBoxLog.Text += "カードをかざしてください" + Environment.NewLine;
} catch(NoServiceException ex) {
textBoxLog.Text += ex.Message + Environment.NewLine;
}
}
// monitor event
private void Monitor_CardInserted(object sender, CardStatusEventArgs e) {
Invoke(new Action(() => {
ReadData();
}));
}
// read data
private void ReadData() {
// reader
using var reader = context.ConnectReader(readerName, SCardShareMode.Shared, SCardProtocol.Any);
var apdu = new CommandApdu(IsoCase.Case2Short, reader.Protocol){
CLA = 0xff,
Instruction = InstructionCode.GetData,
P1 = 0x00,
P2 = 0x00,
Le = 0
};
using (reader.Transaction(SCardReaderDisposition.Leave)) {
// param
var sendPci = SCardPCI.GetPci(reader.Protocol);
var receivePci = new SCardPCI();
var receiveBuffer = new Byte[256];
var command = apdu.ToArray();
// send
var bytesReceived = reader.Transmit(
sendPci,
command,
command.Length,
receivePci,
receiveBuffer,
receiveBuffer.Length);
// response
var responseApdu = new ResponseApdu(receiveBuffer, bytesReceived, IsoCase.Case2Short, reader.Protocol);
if (responseApdu.HasData) {
textBoxReadData.Text = new StringBuilder(BitConverter.ToString(responseApdu.GetData())).ToString();
} else {
textBoxReadData.Text = string.Empty;
}
}
}
// form event
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if(context != null) {
context.Dispose();
}
if(monitor != null) {
monitor.Dispose();
}
}
// 更新button event
private void ButtonReset_Click(object sender, EventArgs e) {
InitializePasori();
}
}
}
その他
SFCardViewr2みたいな挙動にする場合は、更新ボタンなどを付けてInitializePasoriを再実行するようにすれば良いと思います。
そのように改修しました。
参考元
以前に自身のブログで書いたものに未だに細々とアクセスがあるのを知ったので、需要があるのかなと思いqiitaに投稿しました。当時はButtonをClickしたらカードからデータを読む、というエントリしか見つからなかったので、カードをかざしたら読むように書きました。各パラメータはどなたかのblog(qiitaじゃなかったような……)を参考にしたのですが、記憶が曖昧なので(多分このエントリだろうな……というのはあるのですが)参考元は明記しません。