Don't touch me! - Interfacing with a Fingerprint Reader

Published 06 March 07 12:07 AM | Coding4Fun 
  In this installment of the "Some Assembly Required" column, Scott Hanselman creates a Family Fingerprint Manager using .NET 2.0 that interfaces with the Microsoft Fingerprint Reader and the GrFinger SDK from Griaule.
Scott's Blog

Difficulty: Intermediate
Time Required: 1-3 hours
Cost: $50-$100
Software: GrFinger
Hardware: Microsoft FingerPrint Reader
Download: Download

    Scott Hanselman

    Summary: In this installment of the "Some Assembly Required" column, Scott Hanselman creates a Family Fingerprint Manager using .NET 2.0 that interfaces with the Microsoft Fingerprint Reader and the GrFinger SDK from Griaule.

    The Microsoft Fingerprint Reader

    I love my Microsoft Fingerprint Reader and when I got it I knew I had to hack it write some software for it. Since there's already a lot of great security software out there like the Digital Persona software that Microsoft shipped with it as well as 3rd party software like GrFinger's Desktop Identity, I wanted to write something a little different.

    My wife and I made a New Year's Resolution to be more prepared for emergencies and the like in the wake of Hurricane Katrina. I figured, since we've moved all our identification and important papers into the a safety deposit box, why not a copy of our fingerprints as well?

    There are do-it-yourself-at-home fingerprinting kits one can buy, but I had this nice Fingerprint Reader lying around....:)

    Interfacing with the Reader

    Griaule Software out of Brazil has a nice, clean COM API SDK that abstracts away the fingerprint hardware supporting a number of readers including Microsoft's. You can download a trial of their SDK software and use it for 90 days. They also include an open-source driver for the Microsoft Fingerprint Reader so you don't have to use the Digital Persona standard stuff if you don't want to. They've got an excellent sample code section with details on how to interface with a read using VB.NET, C#, Java, VB6, even Excel.

    I started by adding references to their COM APIs and generating an interop assembly as seen in the picture at left. The AxGrFinger control library includes a small control that you can drag on to your WinForms design surface that exposes a number of Fingerprint-related events like FingerDown and ImageRequired that make interfacing with the hardware incredibly easy.

    I created a PictureBox on my WinForm that would display the fingerprint being acquired along with ten other PictureBoxes, one for each finger. The large picture box will appear only when an image is being acquired then disappear after we copy the large acquired image into one of the smaller "fingertip" images.

    The large PictureBox is passed in to a utility class along with a reference to the AxGrFinger control. As the image is acquired a valid "Handle to a Device Context" or HDC (remember those?) is passed into the CapRawImageToHandle method on the AxGrFinger control. When that handle comes back, we just update the large picture box and it displays the newly received image. Once the image has move into the world of WinForms, it's considerably easier to manipulate using the System.Drawing APIs.

        ' Display fingerprint image on screen

        Public Sub PrintBiometricDisplay()

            ' handle to finger image

            Dim handle As System.Drawing.Image = Nothing

            ' screen HDC

            Dim hdc As Integer = GetDC(0)

     

            ' get raw image

            _GrFingerX.CapRawImageToHandle(raw.img, raw.width, raw.height, hdc, handle)

     

            ' draw image on picture box

            If Not (handle Is Nothing) Then

                _pbPic.Image = handle

                _pbPic.Update()

            End If

            ' release screen HDC

            ReleaseDC(0, hdc)

        End Sub

    The images from the large picture box are of very high quality and are copied into the smaller fingers one at a time.

    Loading and Saving the Fingerprints

    There's ten fingerprints (assuming you have ten fingers) to save, but should we save them as one file or ten? I decided that folks would probably want one file per family member using File|Open and File|Save method, but they'd want to reserve the right to export all the fingers as individual (PNG) images.

    I created a very simple in-memory representation of a Fingerprint Database like this. It's actually slightly more complex with custom constructors as such in the actual code, but this is the general idea. I'm going to be storing the high-quality image as a byte array rather than a System.Drawing.Bitmap or Image because a byte array is very easily serialized as XML.

        Public Class Fingerprints

            Public FingerImages(10) As FingerImage

            Public Sub New()

                For i As Integer = 0 To 10

                    FingerImages(i) = New FingerImage()

                Next i

            End Sub

     

            Public Sub AddFingerImage(ByVal finger As String, ByVal image() As Byte)

                Dim i As Int32 = Int32.Parse(finger)

                FingerImages(i - 1) = New FingerImage(image, finger)

            End Sub

     

            Public Function GetImageFromFinger(ByVal finger As String) As Byte()

                For Each fi As FingerImage In Me.FingerImages

                    If (fi.Finger = finger) Then

                        Return fi.Image

                    End If

                Next

                Return Nothing

            End Function

     

        End Class

     

        Public Class FingerImage

            Public _image() As Byte

            Public _finger As String

        End Class

    Each per-person finger database, like scott.finger for example, will be saved as XML similar to the example below. The byte[] is automatically turned into a BASE64'ed string by the XmlSerializer. This might be considered inelegant by some, but disk space is cheap, and the code was fantastically simple. An easy enhancement would ZIP up the file, but the savings would only be about 30-40%.

    <?xml version="1.0"?>
    <Fingerprints xmlns:xsi="
    http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <FingerImages>
        <FingerImage>
          <Image>iVBOR...big opaque BASE64'ed image</Image>
          <Finger>L1</Finger>
        </FingerImage>
    </FingerPrints>

    Loading the fingers back into the Form is the exact opposite of saving. We use a standard Windows File Dialog with the filter set to show only .finger files. The file is deserialized using the XmlSerializer and the images are loaded back into the appropriate PictureBox.

       Private Sub MenuLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuLoad.Click

            Dim OpenFileDialog1 As New OpenFileDialog

     

            '' open "load" dialog

            OpenFileDialog1.Filter = "FINGER files (*.finger)|*.finger|All files (*.*)|*.*"

            OpenFileDialog1.FilterIndex = 1

            OpenFileDialog1.RestoreDirectory = True

            OpenFileDialog1.CheckFileExists = True

     

            '' load image

            If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

     

                Dim x As New XmlSerializer(GetType(Fingerprints))

                Dim newdb As Fingerprints

                Using fs As FileStream = File.OpenRead(OpenFileDialog1.FileName)

                    newdb = CType(x.Deserialize(fs), Fingerprints)

                End Using

     

                For Each item As Control In Me.Controls

                    If IsFingerprintPictureBox(item) Then

                        Dim pic As PictureBox = CType(item, PictureBox)

                        Dim b As Byte() = newdb.GetImageFromFinger(pic.Tag)

                        If (Not b Is Nothing) Then

                            pic.Image = Image.FromStream(New MemoryStream(b))

                        End If

                    End If

                Next

            End If

        End Sub

    I used the Tag Property of the PictureBox to store the name of the finger. The name is also stored in the .finger file and used to correlate the fingers and PictureBoxes.

    The export works similarly, except I save the contents of each PictureBox to the selected directory using the given name as a basefilename. For example, if the user said they wanted to export to Foo.png, I'd create 10 files with names like Foo.l1.png, Foo.r2.png, etc. You can see how easy it is to change image formats using System.Drawing.Image.

                For Each item As Control In Me.Controls

                    If IsFingerprintPictureBox(item) Then

                        Dim pic As PictureBox = CType(item, PictureBox)

                        If Not pic.Image Is Nothing Then

                            Dim filename As String = Path.Combine(Path.GetDirectoryName(ExportFileDialog1.FileName), (Path.GetFileNameWithoutExtension(ExportFileDialog1.FileName) & "." & pic.Name & ".png"))

                            Using m As New MemoryStream

                                pic.Image.Save(filename, Imaging.ImageFormat.Png)

                            End Using

                        End If

                    End If

                Next

    To get this sample to work, you'll need a Microsoft Fingerprint Reader (or other compatible reader) and the Griaule SDK installed. I recommend you uninstall the Digital Persona drivers that came with the Fingerprint Reader otherwise this application may compete for the same hardware if the Digital Persona software is running in the background.

    Conclusion

    There's a number of fun things that could be extended, added, and improved on with this project. Here are some ideas to get you started:

    • Adding a PDF export feature using an open-source .NET PDF Library
    • ...or export to Word using Office Automation and the Microsoft Office Interop Assemblies.
    • Add security by using DPAPI or encrypt the Fingerprint files directly.
    • Add compression by zipping the .finger files up programmatically.

    Have fun and have no fear when faced with the words - Some Assembly Required!

    If you do extend this application, be sure to release the source. Thanks again to Griaule for the use of their SDK.


    Scott Hanselman is the Chief Architect at the Corillian Corporation, an eFinance enabler. He has thirteen years experience developing software in C, C++, VB, COM, and most recently in VB.NET and C#. Scott is proud to be both a Microsoft RD and Architecture MVP. He is co-author of Professional ASP.NET 2.0 with Bill Evjen, available on BookPool.com and Amazon. His thoughts on the Zen of .NET, Programming and Web Services can be found on his blog at http://www.computerzen.com.

    Comment Notification

    If you would like to receive an email when updates are made to this post, please register here

    Subscribe to this post's comments using RSS

    Comments

    # Scott Hanselman's Computer Zen - Coding4Fun: Interfacing with a Microsoft FingerPrint Reader said on March 6, 2007 3:17 AM:

    PingBack from http://www.hanselman.com/blog/Coding4FunInterfacingWithAMicrosoftFingerPrintReader.aspx

    # End Lands » Don't touch me! - Interfacing with a Fingerprint Reader said on March 6, 2007 2:05 PM:

    PingBack from http://endlands.org/dont-touch-me-interfacing-with-a-fingerprint-reader/

    # Shawn Weisfeld said on April 29, 2007 11:13 AM:

    I was playing with my fingerprint reader this weekend and thought I would share what I have worked on

    # skolla said on August 7, 2007 11:02 AM:

    i wana know how you get data from a finger print and then compare two finger prints to see whether they are the same, or just how to get datat from a finger print.

    # David Dyer said on August 12, 2007 3:45 PM:

    This discussion is interesting.  I may try it.

    I’ve had a fingerprint reader for about 6 months, but have some things I don’t like.  Any suggestions would be appreciated.

    1) The program seems slow.  When it recognizes my finger with a ”Ding”, it takes what seems like quite a few seconds to display the menu.  Is there any way to speed this up?

    2) Today it is not displaying the menu at all.  Is there something screwed up?  If so, how can it be fixed?

    3) I’d like to use the reader for Excel programs also, but it will only handle Internet explorer.  How do I get it to process Excel files?

    # Sabin said on February 6, 2008 11:52 AM:

    Hai , i would like to know , how we can access the finger print events in aspx page ....? i want to use this as an web application. i am a c# beginerr ..

    waitng for ur repleys ..

                ...........

    # Coding4Fun said on February 6, 2008 8:59 PM:

    @Sabin: Lets take a step back and think about how we interface with web pages and how they are hosted.  You serve out HTML to your client and your server is what has all the events.  In a web page, you don't have access to the client's computer directly so events won't fire off.

    So long story short, you might be able to, but it really isn't practically plus what I'm thinking of would require an end client to install an Active X control which most people won't do.

    # Roberto said on March 11, 2008 5:40 PM:

    I'm testing Griaule SDK with Microsoft Finger Print in MS Acesss. In Excel Sample the Picture are displayed ok but in Access occur error. On picture control :

    me.Image.Picture=handle

    Any suggestions ou Sample ?

    # kk said on March 15, 2008 10:44 AM:

    Do you know of anything that i can use to encrypt user data (files and folders) with the MS Fingerprint Reader? Its available with the Digital Persona but not the MS reader?

    Thanks

    # Desktop Computers » Coding4Fun : Don’t touch me! - Interfacing with a Fingerprint Reader said on March 19, 2008 2:02 PM:

    PingBack from http://desktopcomputerreviewsblog.info/coding4fun-dont-touch-me-interfacing-with-a-fingerprint-reader/

    # sita said on April 17, 2008 11:26 PM:

    Hi, Can i get the example code in asp.net

    # Coding4Fun said on April 18, 2008 5:01 PM:

    @sita:  While it semi can be done in ASP.Net, really is more of an application that requires a computer.  Instead of a Win32 app, you'd just have a Webpage doing stuff.  You can't have a remote computer do this.

    # Bogdan.email said on September 7, 2008 1:40 AM:

    Hi there Scott,

    I was trying to integrate MS fingerprint reader with the latest SDK from Griaule and I did not succeed. I cannot 'see' the scanner from any of the samples (from SDK or directly from the web - there is a Java app.).

    Do i have to follow some specific steps in order to do the installation ? (ie. first install Griaule - with the driver for DigitalPersona and than plug in the MS FP reader ... or first install the MS FP reader - with the drivers provided on the CD than install the SDK and replace the driver with the one from the SDK ... ???).

    Can i get the app (I did not find a link on the page).

    Can you tell me how can I test that the MS FP reader and the Griaule SDK can 'shake hands' ?

    If you want to can write me at gmail (use my name @gmail.com).

    Thank you in advance,

    Bogdan.

    Leave a Comment

    (required) 
    (optional)
    (required) 
    Page view tracker