There are requirements where you have to integrate a biometric device into your application for things like user authentication, verifying user information, backing up scanned templates into your system database or export it somewhere remotely etc.
For that very purpose, this blog post is written as a getting started guide with a few pieces of source code such that it helps C# developers to save some valuable time with all the troublesome work.
Table Of Contents
You need to download and install them separately from the ZKTeco website.
The download links will be mentioned as you go along with this article.
Device Specifications
This blog intends to provide solution for the device models that are listed below. For a complete list of hardware specification and selection guide, grab a copy of the official document.
Model : ZK4500
SDRAM : 320 KB
Comm : USB 2.0 / 1.1 / 1.0
Template : ZKFinger V10.0
Model : SLK20R
SDRAM : 16 MB
Comm : USB 2.0 / 1.1
Template : ZKFinger V10.0; ISO 19794-2; ANSI 379
Model : ZK9500
SDRAM : 16 MB
Comm : USB 2.0 / 1.1
Template : ZKFinger V10.0
Model : SLK20M
SDRAM : 16 MB
Comm : UART ( 115200bps/TTL3.3V) / USB 2.0
Template : ZKFinger V10.0; ISO 19794-2; ANSI 379
If you are using a different model of device like the ZKTeco K14 or iClock, check out my other article :
Background
Biometric Devices are being used extensively in many corporations through out the world these days. They are widely used in various fields like social insurance, public security, time attendance, fingerprint encryption, embedded systems and many others.
Companies like ZKTeco manufacture biometric access control and Time and Attendance in various shapes and sizes with different set of features per model. They provide a better way of user authentication and security in organizations comparing to the traditional authentication and authorization mechanisms.
Implementing The SDK
ZKFingerSDK is available for the Linux and the Windows platform. Create an account and head over to this link in order to grab yourself a copy of the SDK.
The following steps will guide you and help you to successfully implement a ZKTECO Fingerprint scanner using C# code.
Step 1 - Install The Driver
Install the ZKFinger SDK 5.x / ZKOnline SDK 5.x which comes bundled along with the SDK package.
Step 2 - Add Reference To The Class Library
Once you have successfully installed the driver, depending on your operating system architecture, you will find a dll named libzkfpcsharp.dll either in the Windows/system32 or Windows/syswow64 folder.
You will need to add a reference to that dll from your systems folder in your C# project. Here is how to do it :
Using The Code
You are now ready to implement the fingerprint scanner in your application.
For example:
To initialize the device, in some drivers you have to call upon the Init() method while in some cases the Initialize() method.
Do not get confused !!
Implement The Provided Class
The libzkfpcsharp.dll provides you with a class named zkfp under the namespace libzkfpcsharp.
In your implementation class file, include the namespace libzkfpcsharp and implement the class :
using libzkfpcsharp; // <--- Implement the namespace
namespace YourProject
{
public class YourClassName
{
zkfp fpInstance = new zkfp(); // <--- Create an instance
}
}
Initialize The Device
public void InitializeDevice()
{
int callBackCode = fpInstance.Initialize();
if (zkfp.ZKFP_ERR_OK == callBackCode)
{
int nCount = fpInstance.GetDeviceCount();
if (nCount > 0)
{
for (int index = 1; index <= nCount; index++)
{
// Hold these indexes somewere
// It represents the index of the device you wish to connect to
}
// Connected Successfully
}
}
else { /* Unable to initialize, Clear previous resources */ }
}
Connect A Device
Connecting to a device requires the index of the device you wish to connect to. The index can be retrieved by calling the GetDeviceCount method from the above section.
Besides establishing a connection to the device, you need to initialize a few more things like the fingerprint image height and width with can be obtained by calling the GetParameters method. It is recommended to use the image size parameters provided by the device instead of using a static height and width.
public void ConnectDevice(int deviceIndex)
{
int openDeviceCallBackCode = fpInstance.OpenDevice(deviceIndex);
if (zkfp.ZKFP_ERR_OK != openDeviceCallBackCode)
{
// Unable to connect with the device
return;
}
RegisterCount = 0;
regTempLen = 0;
iFid = 1;
for (int i = 0; i < REGISTER_FINGER_COUNT; i++)
{
RegTmps[i] = new byte[2048];
}
byte[] paramValue = new byte[4];
// Retrieve the fingerprint image width
int size = 4;
fpInstance.GetParameters(PARAM_CODE_IMAGE_WIDTH, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref mfpWidth);
// Retrieve the fingerprint image height
size = 4;
fpInstance.GetParameters(PARAM_CODE_IMAGE_HEIGHT, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref mfpHeight);
FPBuffer = new byte[mfpWidth * mfpHeight];
// Create a thread to retrieve any new fingerprint and handle device events
captureThread = new Thread(new ThreadStart(DoCapture));
captureThread.IsBackground = true;
captureThread.Start();
bIsTimeToDie = false;
}
Acquiring Fingerprints
Acquiring fingerprint is normally handled by calling the AcquireFingerprint method which gets called upon time to time by the thread that we just setup in the previous section.
On a successful fingerprint capture, it passes the message to the form handle which then acts upon based on the type of message retrieved.
For sending message we need to setup a form handle such that the SendMessage command can pass the message to the respected Form.
const int MESSAGE_CAPTURED_OK = 0x0400 + 6;
byte[] CapTmp = new byte[2048];
int cbCapTmp = 2048;
IntPtr FormHandle = IntPtr.Zero; // To hold the handle of the form
private void DoCapture()
{
try
{
while (!bIsTimeToDie)
{
cbCapTmp = 2048;
int ret = fpInstance.AcquireFingerprint(FPBuffer, CapTmp, ref cbCapTmp);
if (ret == zkfp.ZKFP_ERR_OK)
{
SendMessage(FormHandle, MESSAGE_CAPTURED_OK, IntPtr.Zero, IntPtr.Zero);
}
Thread.Sleep(100);
}
}
catch { }
}
[DllImport("user32.dll", EntryPoint = "SendMessageA")]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
Â
private void FingerPrintControl_Load(object sender, EventArgs e) { FormHandle = this.Handle; }
Â
Basically what we are doing here is, passing the message retrieved from the device to the current winform handle which then handles the message.
If you are using any other type of application and you do not wish to use the SendMessage PInvoke commands and the following process, you can implement it your own way. It is completely upto you.
Handling Messages
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case MESSAGE_CAPTURED_OK:
// All your registration and verification code needs to be handled here
if (isRegistering)
{
// Code to be executed in case of registration
// Checkout the 'Registration Case' explained below
}
else
{
// Code to be executed in case of fingerprint verification
// and any random fingerprint
// Checkout the 'Identification and Match' case explained below
}
break;
default:
base.DefWndProc(ref m);
break;
}
}
Fingerprint Acquisition : Registration Case
Registration is generally a 3 step process. i.e The current user must input his same fingerprint 3 times continuously in order to be successfully enrolled.
private void RegistrationCase()
{
int fid = 0, score = 0;
int returnValue = fpInstance.Identify(CapTmp, ref fid, ref score);
if (zkfp.ZKFP_ERR_OK == returnValue)
{
// Remove the previous fingerprint from memory
int deleteCode = fpInstance.DelRegTemplate(fid);
if (deleteCode != zkfp.ZKFP_ERR_OK)
{
// The fingerprint is already registered
return;
}
}
// Check if the user has enterd the fingerprint 3 times or not
if (RegisterCount > 0 && fpInstance.Match(CapTmp, RegTmps[RegisterCount - 1]) <= 0)
{
return;
}
Array.Copy(CapTmp, RegTmps[RegisterCount], cbCapTmp);
RegisterCount++;
if (RegisterCount >= REGISTER_FINGER_COUNT)
{
RegisterCount = 0;
// Generate a fingerprint template by the combination of 3 successfully fingerprint acquisition
returnValue = fpInstance.GenerateRegTemplate(RegTmps[0], RegTmps[1], RegTmps[2], RegTmp, ref regTempLen);
if (zkfp.ZKFP_ERR_OK == returnValue)
{
// LOAD TEMPLATE TO MEMORY
returnValue = fpInstance.AddRegTemplate(iFid, RegTmp);
if (zkfp.ZKFP_ERR_OK == returnValue)
{
string fingerPrintTemplate = string.Empty;
zkfp.Blob2Base64String(RegTmp, regTempLen, ref fingerPrintTemplate);
// ******** fingerPrintTemplate holdes the successfully enrolled fingerprint *******
}
else
{
// Failed to add template
}
}
else
{
// Unable to enroll due to some reason
}
return;
}
else
{
// Requires 3 fingerprints to successfully enroll
// Ask for the same fingerprint 2 more times
int remainingCont = REGISTER_FINGER_COUNT - RegisterCount;
}
}
Fingerprint Acquisition : Identification and Match Case
private void RandomFingerprintCase()
{
// Identifying, Matching and handling anonymous fingerprints needs to be done here
if (regTempLen <= 0)
{
// Un-identified fingerprint
return;
}
if (isIdentifying)
{
int ret = zkfp.ZKFP_ERR_OK;
int fid = 0, score = 0;
ret = fpInstance.Identify(CapTmp, ref fid, ref score);
if (zkfp.ZKFP_ERR_OK == ret)
{
// Identification Success
return;
}
else
{
// Identification Failed
return;
}
}
else
{
int ret = fpInstance.Match(CapTmp, RegTmp);
if (0 < ret)
{
// Match Success
return;
}
else
{
// Match Failed
return;
}
}
}
Disconnect The Device
While disconnecting from the device, you also need to abort any running threads and free up the resources. Here is how you should do it :
private void DisconnectDevice()
{
int result = fpInstance.CloseDevice(); // Close the connection
captureThread.Abort(); // Abort any running threads
if (result == zkfp.ZKFP_ERR_OK)
{
result = fpInstance.Finalize(); // Clear the resources
if (result == zkfp.ZKFP_ERR_OK)
{
// Reset any variables and data if necessary
}
}
}
Head over to the GitHub code sample and see it in full action.
Here is a demo app if you wish to see how if functions. Don`t forget to install the driver first.
Go Beyond the frontiers of yourself. Peace !!!
Hello,
I’m trying to use your example code with a project, using SQL server, but I can’t find where is the variable to save at my Database , and compare with the registers, I think this variable is ret but this his a int, can you helpme whit this?
I’m using the biometric model SLK20R and SQLServer in C#
if you solve it can you send me the function that save fingerprint to database and the function that compare with the registers please !?
I have written a short procedure on how to compare user fingerprints here
Hello Valentin,
If you wish to save the users fingerprint template after a successful enrollment…
Then you will get the users fingerprint template in line number 268 in the FingerprintControl class
The template is only fully generated after 3 successful capture.
Hi Ozesh,
If I get the registerted fingerprint template and add it to a picturebox it is black? Am I doing something wrong because I am using the BitmapFormat.GetBitmap to create the image
Hello Rikus,
Yes BitmapFormat.GetBitmap is what you should be using to generate the fingerprint template.
You need to check a few things to get a good image :
1. Check to see if the mfpWidth and mfpHeight matches the one that is retrieved from the code at Line 123 And Line 127 and not some random value that you might be using.
2. Are you successfully obtaining the fingerprint image at Line 577 ?
3. Your FPBuffer length should be the multiple of mfpWidth and mfpHeight.
nable to load DLL ‘libzkfp.dll’: The specified module could not be found. (Exception from HRESULT: 0x8007007E)
Hello Salman,
You need to first install the ZKFinger SDK 5.x / ZKOnline SDK 5.x driver successfully.
The next step would be to reference the dll in your project.
Hello Ozesh,
Thank you for the source code it worked very well in my Laptop and connected perfect with zk4500 but when i try to connect zk4500 in my PC the application return code -6
Unable to connect with the device! ( Return Code: -6 )
what should i do to solve it?
the button Free resources Not work !
thank you
Hello Motee,
There might be many reasons behind your current issue.
Two possible reasons might include:
1. The device driver is not properly installed.
2. There is something wrong with the usb port where you have connected the device.
Also do check for potential issues in the windows event viewer regarding the connected device.
Hello,
Thank you for the code, I try to pass to the fpInstance.AddRegTemplate the template that it´s save in a DB, but always the function return -13 any idea?
I don´t call the fpInstance.GenerateRegTemplate because in teory the template that is save in the DB it’s the real
Hello Mario,
-13 is the error code for possibly an invalid fingerprint template.
1. Check to see if the RegTmp that you are providing to the device is a valid template which you have obtained with 3 successful enrollments.
2. The Zkteco Scanner can only accept a verified template from any zkteco devices and not any other model of devices rather than a Zkteco model.
Hello Ozesh,
How do you get the registerted finger template as an image?
During the registration process, you can obtain the registered template via the FingerPrintControl class which at that time is retrieved from the systems memory. You can simply save the bitmap as an image file if you want to at this point.
Hello Ozesh,
Thank you for the source code. I have learned a lot from it. I just want to ask if there are any possibilities that those libraries may work with this ZK TX628 model of biometrics device. I am unable to detect any connected device so far. Am I missing anything? Please advice. Thank you.
Hello Aubrey,
The Zkfingerprint Scanner sdk wont work with your device model.
I think my other article C# ZKTeco Biometric Device Getting Started and the SDK that it uses will help you out with your device.
Can you help me with WPF application?
I want to show this in a user control.
Protected override void DefWndProc(ref Message m) I can’t use it for WPF its belong to WinForm
Hello Zahid,
The WPF architecture doesnt expose the DefWndProc api.
I think this might help.
How to implement this on asp.net web application? Is it possible?
If i tried its only working asp.net windows application.
Your replays are highly appreciated
Hello Shafeek,
No, you can`t integrate a ZKTeco Fingerprint scanner in a web application directly.
However, there are other approaches to achieve the web application integration.
Some of them are :
1. Via an intermediate custom application to handle fingerprint enrollments and exporting data to the web api or server.
2. Via the ADMS feature which are available in some of ZKTeco models.
Thank You Ozesh
Thank you Ozesh. But I am trying to create a image of the 3 finger images that are merged? Can I save that merged template to my database for a small attendance program I am writing and then match it with a new scanned finger print to verify it?
Hello Rikus,
Yes, the merged template can be easily saved and later on used to verify the user.
But note that, the fingerprint template and the fingerprint image are two different things.
Hello my device is Bio31M. The application can’t detect the device. May i know what is the problem?
Guys does anybody know if this lib can be used to vb6 classic? If not, is there a library for zk9500 designed for vb6 classic?
Thank you for your response.
Hello.
I need your help to develop web service for my asp.net project. i want to syncing my devices. please share your contact where i will communicate you. thank you very much.
Hello Anjum,
You can contact me directly via ojthapa@gmail.com
Please mention ‘via debuggershub’ in the email subject as I dont usually check emails, getting a lot these days.
Thank you.
Does this libzkfpcsharp supports ZK7500 FINGER PRINT READER DEVICE?
Hello Rajaram,
I have not got the chance to try it out with the ZK7500 model.
If you have tested it out and if it works for you, Please do inform.
I will include ZK7500 as well as one of the supported devices.
Thank you.
Hello Ozesh, thank you.
I need capture the fingerprint with the SLK20R and then put them on the SilkBio-100TC device. It’s possible?
Tank you so much.
Sorry for my english 🙂
Hello Luis,
I think so. I tried out something similar once and it worked.
There is a sort of backward compatibility with the Zkteco devices.
It seems that a higher model of device which uses a higher version of the biometric algorithm supports fingerprint templates from those of a lower one.
However, a lower model device using a lower biometric algorithm might not support a fingerprint template from a higher one.
Thank you.
thanks for the code, I managed to save and read from sql server with c#!
I need Your Help.How you saved and read from sql server
thank you for sample !!
everything ok and working all codes.
BUT
I want to save the finger record dtabase MS SQL Server.
share sample codes ?
Thank you !!!
Did you saved Records in SQL Server?
Question Does this library work with slk20r, zk9500, slk20m readers? Have you verified it ?
Yes It does with SLK20R, ZK950.
Thanks to help and share you knowledge
can i save the enrollment to database and verify from database
Hey Mohamed,
Yes you can export the enrollments to your database.
But No, it is not possible to verify from database.
The verification requires running a certain algorithm through the fingerprint template,
which can only be done by the device.
hii Ozesh,
I have text box control in aspx page i need to ingrate Magnetic stripe card whenever user swipe card then i need to fetch card information and display on web page so how can i do this?
which approach should use for this??
can you pls help for this??
Hello my friend Ozesh
Thanks for sharing the information and thanks for your help
I try to store and compare the fingerprints of 100,000 people, but there is no device that receives this large number. Is there a solution to store and compare fingerprints from the database or increase the storage space of devices
wgen remove check in prefer 32- bit in build tab in project application
application not work
pls auto connection device when power fail
Hi, thanks for the code.. so basically after enrollment and saving users(many) individual fingerprint templates on the database.
If I need to verify a person fingerprint, I need to load all fingerprint templates(from DB) to the device and iterate and compare using the “fpInstance.Identify()”.
So if there are thousands of users which I think the device SDRAM cannot hold,then I should write(fingerprint template) to device,compare(identify),erase and write again until I finish comparing or have the exact match.
Am I understanding it right? thanks again and Ill appreciate the reply.
can we capture real time device punch and save them into database?
Okay, so everything great thank you very much !! now how to upload the finger template etc to the different devices ?