I am learning to develop the functionality for this ZK4500 fingerprint scanner with C# to save the finger data into a .dat file. As I launch this for first time (there is no .dat file yet), i can add as many fingers as I want. But, if I close this and open it again to add a new finger, it says “Enroll failed, error code=-13” even when the previously enrolled fingers are there there.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using libzkfpcsharp;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using Sample;
using System.Diagnostics;
namespace Demo
{
public partial class Form1 : Form
{
IntPtr mDevHandle = IntPtr.Zero;
IntPtr mDBHandle = IntPtr.Zero;
IntPtr FormHandle = IntPtr.Zero;
bool bIsTimeToDie = false;
bool IsRegister = false;
bool bIdentify = true;
byte[] FPBuffer;
int RegisterCount = 0;
const int REGISTER_FINGER_COUNT = 3;
byte[][] RegTmps = new byte[3][];
byte[] RegTmp = new byte[2048];
byte[] CapTmp = new byte[2048];
int cbCapTmp = 2048;
int cbRegTmp = 0;
int iFid = 1;
Thread captureThread = null;
private int mfpWidth = 0;
private int mfpHeight = 0;
const int MESSAGE_CAPTURED_OK = 0x0400 + 6;
private const string FINGERPRINT_DATA_FILE = "fingerprint_template.dat";
[DllImport("user32.dll", EntryPoint = "SendMessageA")]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
public Form1()
{
InitializeComponent();
}
private void bnInit_Click(object sender, EventArgs e)
{
cmbIdx.Items.Clear();
int ret = zkfperrdef.ZKFP_ERR_OK;
if ((ret = zkfp2.Init()) == zkfperrdef.ZKFP_ERR_OK)
{
int nCount = zkfp2.GetDeviceCount();
if (nCount > 0)
{
for (int i = 0; i < nCount; i++)
{
cmbIdx.Items.Add(i.ToString());
}
cmbIdx.SelectedIndex = 0;
bnInit.Enabled = false;
bnFree.Enabled = true;
bnOpen.Enabled = true;
}
else
{
zkfp2.Terminate();
MessageBox.Show("No device connected!");
}
}
else
{
MessageBox.Show("Initialize fail, ret=" + ret + " !");
}
}
private void LoadFingerprintData()
{
if (File.Exists(FINGERPRINT_DATA_FILE))
{
try
{
using (FileStream fs = new FileStream(FINGERPRINT_DATA_FILE, FileMode.Open))
{
using (BinaryReader reader = new BinaryReader(fs))
{
while (fs.Position < fs.Length)
{
int fid = reader.ReadInt32(); // Read the fingerprint ID
int templateLength = reader.ReadInt32(); // Read the length of the template
byte[] template = reader.ReadBytes(templateLength); // Read the template
// Add the loaded fingerprint template to the database
int ret = zkfp2.DBAdd(mDBHandle, fid, template);
if (ret == zkfp.ZKFP_ERR_OK)
{
textRes.Text = $"Fingerprint with ID {fid} loaded successfully.";
}
else
{
textRes.Text = $"Failed to add fingerprint with ID {fid}. Error: {ret}";
}
// Update the fingerprint ID counter so it doesn't conflict
iFid = fid + 1;
}
}
}
}
catch (Exception ex)
{
textRes.Text = "Error loading fingerprint data: " + ex.Message;
}
}
else
{
textRes.Text = "No saved fingerprint data found.";
}
}
private void SaveFingerprintData(int fid, byte[] fingerprintTemplate)
{
try
{
// Open file in append mode
using (FileStream fs = new FileStream(FINGERPRINT_DATA_FILE, FileMode.Append))
{
using (BinaryWriter writer = new BinaryWriter(fs))
{
writer.Write(fid); // Write fingerprint ID
writer.Write(fingerprintTemplate.Length); // Write the length of the fingerprint template
writer.Write(fingerprintTemplate); // Write the fingerprint template itself
}
}
textRes.Text = "Fingerprint data saved successfully.";
}
catch (Exception ex)
{
textRes.Text = "Error saving fingerprint data: " + ex.Message;
}
}
private void bnFree_Click(object sender, EventArgs e)
{
zkfp2.Terminate();
cbRegTmp = 0;
bnInit.Enabled = true;
bnFree.Enabled = false;
bnOpen.Enabled = false;
bnClose.Enabled = false;
bnEnroll.Enabled = false;
bnVerify.Enabled = false;
bnIdentify.Enabled = false;
}
private void bnOpen_Click(object sender, EventArgs e)
{
int ret = zkfp.ZKFP_ERR_OK;
if (IntPtr.Zero == (mDevHandle = zkfp2.OpenDevice(cmbIdx.SelectedIndex)))
{
MessageBox.Show("OpenDevice fail");
return;
}
if (IntPtr.Zero == (mDBHandle = zkfp2.DBInit()))
{
MessageBox.Show("Init DB fail");
zkfp2.CloseDevice(mDevHandle);
mDevHandle = IntPtr.Zero;
return;
}
// Load fingerprint data only after the device and DB are successfully initialized
LoadFingerprintData();
bnInit.Enabled = false;
bnFree.Enabled = true;
bnOpen.Enabled = false;
bnClose.Enabled = true;
bnEnroll.Enabled = true;
bnVerify.Enabled = true;
bnIdentify.Enabled = true;
RegisterCount = 0;
cbRegTmp = 0;
iFid = 1;
for (int i = 0; i < 3; i++)
{
RegTmps[i] = new byte[2048];
}
byte[] paramValue = new byte[4];
int size = 4;
zkfp2.GetParameters(mDevHandle, 1, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref mfpWidth);
size = 4;
zkfp2.GetParameters(mDevHandle, 2, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref mfpHeight);
FPBuffer = new byte[mfpWidth * mfpHeight];
captureThread = new Thread(new ThreadStart(DoCapture));
captureThread.IsBackground = true;
captureThread.Start();
bIsTimeToDie = false;
textRes.Text = "Device opened successfully.";
}
private void DoCapture()
{
while (!bIsTimeToDie)
{
cbCapTmp = 2048;
int ret = zkfp2.AcquireFingerprint(mDevHandle, FPBuffer, CapTmp, ref cbCapTmp);
if (ret == zkfp.ZKFP_ERR_OK)
{
SendMessage(FormHandle, MESSAGE_CAPTURED_OK, IntPtr.Zero, IntPtr.Zero);
}
Thread.Sleep(200);
}
}
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case MESSAGE_CAPTURED_OK:
{
MemoryStream ms = new MemoryStream();
BitmapFormat.GetBitmap(FPBuffer, mfpWidth, mfpHeight, ref ms);
Bitmap bmp = new Bitmap(ms);
this.picFPImg.Image = bmp;
if (IsRegister)
{
int ret = zkfp.ZKFP_ERR_OK;
int fid = 0, score = 0;
ret = zkfp2.DBIdentify(mDBHandle, CapTmp, ref fid, ref score);
if (zkfp.ZKFP_ERR_OK == ret)
{
textRes.Text = "This finger was already registered by " + fid + "!";
return;
}
if (RegisterCount > 0 && zkfp2.DBMatch(mDBHandle, CapTmp, RegTmps[RegisterCount - 1]) <= 0)
{
textRes.Text = "Please press the same finger 3 times for the enrollment";
return;
}
Array.Copy(CapTmp, RegTmps[RegisterCount], cbCapTmp);
RegisterCount++;
if (RegisterCount >= REGISTER_FINGER_COUNT)
{
RegisterCount = 0;
if (zkfp.ZKFP_ERR_OK == (ret = zkfp2.DBMerge(mDBHandle, RegTmps[0], RegTmps[1], RegTmps[2], RegTmp, ref cbRegTmp)) &&
zkfp.ZKFP_ERR_OK == (ret = zkfp2.DBAdd(mDBHandle, iFid, RegTmp)))
{
iFid++;
textRes.Text = "Enroll successful";
SaveFingerprintData(iFid - 1, RegTmp); // Use iFid - 1 because it's incremented after adding
}
else
{
textRes.Text = "Enroll failed, error code=" + ret;
}
IsRegister = false;
return;
}
else
{
textRes.Text = "You need to press the " + (REGISTER_FINGER_COUNT - RegisterCount) + " times fingerprint";
}
}
else
{
if (cbRegTmp <= 0)
{
textRes.Text = "Please register your finger first!";
return;
}
if (bIdentify)
{
int ret = zkfp.ZKFP_ERR_OK;
int fid = 0, score = 0;
ret = zkfp2.DBIdentify(mDBHandle, CapTmp, ref fid, ref score);
if (zkfp.ZKFP_ERR_OK == ret)
{
textRes.Text = "Identify succ, fid= " + fid + ",score=" + score + "!";
return;
}
else
{
textRes.Text = "Identify failed, ret= " + ret;
return;
}
}
else
{
int ret = zkfp2.DBMatch(mDBHandle, CapTmp, RegTmp);
if (0 < ret)
{
textRes.Text = "Match finger succ, score=" + ret + "!";
return;
}
else
{
textRes.Text = "Match finger failed, ret= " + ret;
return;
}
}
}
}
break;
default:
base.DefWndProc(ref m);
break;
}
}
private void Form1_Load(object sender, EventArgs e)
{
FormHandle = this.Handle;
}
private void CloseDevice()
{
if (IntPtr.Zero != mDevHandle)
{
bIsTimeToDie = true;
Thread.Sleep(1000);
captureThread.Join();
zkfp2.CloseDevice(mDevHandle);
mDevHandle = IntPtr.Zero;
}
}
private void bnClose_Click(object sender, EventArgs e)
{
CloseDevice();
RegisterCount = 0;
Thread.Sleep(1000);
bnInit.Enabled = false;
bnFree.Enabled = true;
bnOpen.Enabled = true;
bnClose.Enabled = false;
bnEnroll.Enabled = false;
bnVerify.Enabled = false;
bnIdentify.Enabled = false;
}
private void bnEnroll_Click(object sender, EventArgs e)
{
if (!IsRegister)
{
IsRegister = true;
RegisterCount = 0;
cbRegTmp = 0;
textRes.Text = "Please press your finger 3 times!";
}
}
private void bnIdentify_Click(object sender, EventArgs e)
{
if (!bIdentify)
{
bIdentify = true;
textRes.Text = "Please press your finger!";
}
}
private void bnVerify_Click(object sender, EventArgs e)
{
if (bIdentify)
{
bIdentify = false;
textRes.Text = "Please press your finger!";
}
}
}
}
I have to make sure Save and Load iFid Correctly
iFid = fid + 1;
What I want is, to be able to add and save other finger data even if I close and open the app again.
0
It fixed now, Remove this line from bnOpen_Click:
iFid = 1;