Colabora .NET

Control de Acceso Mediante Huellas Digitales

[Utilizando el Microsoft FingerPrint Reader]

 

Fecha: 11/Oct/2006 (05/10/2006)
Autor: Iván E. Ordoñez O. - ivan_elias_o_o@hotmail.com

 


Introducción

Cuando en trabajo me pidieron buscarle solución al chequeo de horarios y control de asistencia del personal para evitar que un empleado marque la entrada de otro tome como mejor opción implementar un sistema que utilizara un lector de Huellas digitales para marar la hora de entrada y salida de los empleados; pero, como alguno de ustedes se abra dado cuenta que la mayoría de estos Lectores vienen si el SDK para Programarlos por lo que me vi en la obligación de encontrar uno que fuera gratuito o bien programarlo desde cero (Situación en la que no me quería ver debido a la fecha de entrega ;) ), entre tanto buscar encontré una librería Gratis para Desarrollar sobre Varios Lectores Entre ellos El Microsoft FingerPrint Reader que es el que yo utilice, publicada por GRIAULE llamado GrFinger FREE 4.1 disponible para descargar

 

Nota:

Debido a lo Extenso del Código solo Detallaré las Dos (2) Clases Principales: DBCass (Donde Buscamos y Comparamos el Resultado que arroja el lector y Comparamos, Con los Registros en la Base de Datos y la Clase "Util.vb" que es la que control del Lector de Huellas.....
 

 

Ojo!!! Debes Instalar GrFinger_Free_Installer.exe. y Crear La Base de Datos en SQL Server 2005 para Poder Correr La aplicacion

Comencemos... Veamos El código:

 

El Código de la Clase: DBClass.vb

Imports System.Data.SqlClient
Imports System.Runtime.InteropServices

Public Class TTemplate
    Public tpt(GrFingerXLib.GRConstants.GR_MAX_SIZE_TEMPLATE) As Byte
    Public Size As Long
End Class

Public Structure TTemplates
    Public ID As Integer
    Public Cedula As Integer
    Public template As TTemplate
End Structure

Public Class DBClass
    Dim connection As New SqlConnection

    Public Function OpenDB() As Boolean
        Try
            connection = New SqlClient.SqlConnection(My.Settings.AccesoConnectionString)
            Return True
        Catch
            Return False
        End Try
    End Function

    Public Sub closeDB()
        connection.Close()
    End Sub

    Public Sub clearEmpleadoDB(ByVal Cedula As Integer)
        Dim sqlCMD As SqlCommand = New SqlCommand("DELETE FROM Biometrica where Cedula=" & _
		Cedula, connection)
        sqlCMD.Connection.Open()
        sqlCMD.ExecuteNonQuery()
        sqlCMD.Connection.Close()
    End Sub

    Public Function AddTemplate(ByRef template As TTemplate, _
		ByVal Cedula As Integer, ByVal contDed As Integer) As Long
        Dim da As New SqlDataAdapter("select RowID, Cedula, Template from Biometrica", _
		connection)
        da.InsertCommand = New SqlCommand( _
		"INSERT INTO Biometrica (cedula, template) Values(" & _
		Cedula & ", @template)", connection)
        da.InsertCommand.CommandType = CommandType.Text
        da.InsertCommand.Parameters.Add("@template", SqlDbType.VarBinary, _
		template.Size, "template")

        connection.Open()

        Dim TBio As DataSet = New DataSet
        da.Fill(TBio, "Biometrica")

        Dim newRow As DataRow = TBio.Tables("Biometrica").NewRow()
        newRow("Cedula") = Cedula
        newRow("template") = template.tpt
        TBio.Tables("Biometrica").Rows.Add(newRow)
        ' ContHuellas += 1
        Select Case contDed
            Case 1
                If Principal.ActiveForm.Name = "Wizard" Then
                    Wizard.PBDedos.Image = My.Resources.Indice
                Else
                    AgregarHuellas.PBDedos.Image = My.Resources.Indice
                End If
                da.Update(TBio, "Biometrica")
                connection.Close()
            Case 2
                If Principal.ActiveForm.Name = "Wizard" Then
                    Wizard.PBDedos.Image = My.Resources.Indice
                Else
                    AgregarHuellas.PBDedos.Image = My.Resources.Indice
                End If
                da.Update(TBio, "Biometrica")
                connection.Close()
            Case 3
                If Principal.ActiveForm.Name = "Wizard" Then
                    Wizard.PBDedos.Image = My.Resources.Indice
                Else
                    AgregarHuellas.PBDedos.Image = My.Resources.Indice
                End If
                da.Update(TBio, "Biometrica")
                connection.Close()

        End Select
        Return newRow("ID")
    End Function

    Private Sub OnRowUpdated(ByVal sender As Object, ByVal args As SqlRowUpdatedEventArgs)

    End Sub

    Public Function getTemplates() As TTemplates()
        Dim ds As New DataSet
        Dim da As New SqlDataAdapter( _
		"select RowID, Cedula, Template from Biometrica order by Cedula Desc", _
		connection)
        Dim ttpts As TTemplates()
        Dim i As Integer

        da.Fill(ds)
        Dim tpts As DataRowCollection = ds.Tables(0).Rows
        ReDim ttpts(tpts.Count)
        If tpts.Count = 0 Then Return ttpts
        For i = 1 To tpts.Count - 1
            ttpts(i).template = New TTemplate
            ttpts(i).ID = tpts.Item(i).Item("RowID")
            ttpts(i).Cedula = tpts.Item(i).Item("Cedula")
            ttpts(i).template.tpt = tpts.Item(i).Item("template")
            ttpts(i).template.Size = ttpts(i).template.tpt.Length
        Next
        Return ttpts
    End Function

    Public Function getTemplate(ByVal Cedula As Long) As Byte()
        Dim ds As New DataSet
        Dim da As New SqlDataAdapter( _
		"select ID, Cedula, Template from Biometrica where Cedula = " & _
		Cedula, connection)
        Dim tpt As New TTemplate
        da.Fill(ds)
        Dim tpts As DataRowCollection = ds.Tables(0).Rows
        If tpts.Count <> 1 Then Return Nothing
        Return tpts.Item(0).Item("template")
    End Function

End Class

Comencemos... Veamos El código:

 

El Código de la Clase: Util.vb

Imports GrFingerXLib
Imports Microsoft.VisualBasic
'Primero Creamos la estructura don vamos a almacenar  la imagen obtenida del Lector de Huellas
Public Structure RawImage
'img es donde Guardamos la data de la Imagen
    Public img As Object

' width es el ancho de la imagen 
    Public width As Long
' width es el alto de la imagen
    Public height As Long
' width es la Resolucion de la imagen
    Public res As Long
End Structure

'Creamos la Clase Util
Public Class Util
    'Definimos estas Constantes para hacer mas Limpio el Código
    Public Const ERR_CANT_OPEN_BD As Integer = -999
    Public Const ERR_INVALID_ID As Integer = -998
    Public Const ERR_INVALID_TEMPLATE As Integer = -997

' Importamos las Funciones HDC Necesarias
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Int32) As Int32
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Int32, _
	ByVal hdc As Int32) As Int32

' La Ultima Imagen Adquirida
    Public raw As RawImage
' Los Datos y Coincidencias de la Ultima Imagen Adquirida
    Public template As New TTemplate
' Hacemos Referencia a la Clase DBClass.vb
    Public DB As DBClass
' Lista donde se Mostraran Los Mensajes Obtenidos del Lector
    de HUellas
    Private _lbLog As ListBox
'PictureBox Donde Mostraremos la Imagen adquirida del Lector
    Private _pbPic As PictureBox
' Creamos la el Componente de la Libvreria para manejar
    el Lector de Huellas
    Private _GrFingerX As AxGrFingerXLib.AxGrFingerXCtrl

' Método Constructor Nulo de la Clase UTIL.vb
    Sub New()

    End Sub

' Método Constructor donde le decimos a la clase
        los controles que utilizaremos en el formulario basandonos en los que declaramos
        anteriormente     Public Sub New(ByRef lbLog As ListBox, ByRef pbPic As PictureBox, _
 ByRef GrFingerX As AxGrFingerXLib.AxGrFingerXCtrl)
        _lbLog = lbLog
        _pbPic = pbPic
        _GrFingerX = GrFingerX
    End Sub


' Método que Maneja Los Mensajes 
    Public Sub WriteLog(ByVal message As String)
        _lbLog.Items.Add(message)
        _lbLog.SelectedIndex = _lbLog.Items.Count - 1
        _lbLog.ClearSelected()
    End Sub


' Método que maneja la Errores arrojados por GrFingerX.dll
    Public Sub WriteError(ByVal errorCode As Integer)
        Select Case errorCode
            Case GRConstants.GR_ERROR_INITIALIZE_FAIL
                WriteLog("Error al Iniciar GrFingerX. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_NOT_INITIALIZED
                WriteLog("La Biblioteca de Clases no Ha Sido inicialiuzada. (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_FAIL_LICENSE_READ
                WriteLog("Falla de Licencia. Verifique el manual (Error:" & errorCode & ")")
                MessageBox.Show("Falla de Licencia. Verifique el manual")
            Case GRConstants.GR_ERROR_NO_VALID_LICENSE
                WriteLog("La Licencia no es Válida. Verifique el Manual. (Error:" & _
		errorCode & ")")
                MessageBox.Show("La Licencia no es Válida. Verifique el Manual.")
            Case GRConstants.GR_ERROR_NULL_ARGUMENT
                WriteLog("El Parámetro tiene un Valor Nulo. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_FAIL
                WriteLog("Error Creando Imagen. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_ALLOC
                WriteLog("Error Creando El Contexto. Volcado de Memoria. (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_PARAMETERS
                WriteLog("Uno o Mas Parametros Está fuera de Rango. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_WRONG_USE
                WriteLog("No Se Puede Inicializar esta Funcion en este Momento. (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_EXTRACT
                WriteLog("Falló al Obtener Template. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_SIZE_OFF_RANGE
                WriteLog("La Imagen Obtenida es Demasiado Grande o Pequeña.  (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_RES_OFF_RANGE
                WriteLog("La Imagen Tiene Muy Alta o Muy Baja resolution. (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_CONTEXT_NOT_CREATED
                WriteLog("No se Pudo Crear el Contexto. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_INVALID_CONTEXT
                WriteLog("El Contexto No Existe. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_CONNECT_SENSOR
                WriteLog("Ocurrio un Error Cuando se Inicializaba el Lector. (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_CAPTURING
                WriteLog("Error de Captura. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_CANCEL_CAPTURING
                WriteLog("Error al Finalizar Captura. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_INVALID_ID_SENSOR
                WriteLog("El idSensor es Invalido. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_SENSOR_NOT_CAPTURING
                WriteLog("El Sensor no está Capturando. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_INVALID_EXT
                WriteLog("El archivo Tiene una Extension Desconocida. (Error:" & _
		errorCode & ")")
            Case GRConstants.GR_ERROR_INVALID_FILENAME
                WriteLog("El Nombre del Archivo es Inválido. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_INVALID_FILETYPE
                WriteLog("El Tipo de Archivo es Inválido. (Error:" & errorCode & ")")
            Case GRConstants.GR_ERROR_SENSOR
                WriteLog("El Lector Arrojó Un Error. (Error:" & errorCode & ")")
            Case ERR_INVALID_TEMPLATE
                WriteLog("Template Invalido. (Error:" & errorCode & ")")
            Case ERR_INVALID_ID
                WriteLog("ID Invalido. (Error:" & errorCode & ")")
            Case ERR_CANT_OPEN_BD
                WriteLog("Error al Conectar La Base de Datos. (Error:" & errorCode & ")")
            Case Else
                WriteLog("Error:" & errorCode)
        End Select
    End Sub


'Verificamos si la Data Obtenida de la Imagen es Válida
    Private Function TemplateIsValid() As Boolean
 ' Verifica el tamaño del Lector
        Return template.Size > 0
    End Function


' Método que Inicializa el Uso Lector     Public Function InitializeGrFinger() As Integer
        Dim err As Integer
        DB = New DBClass
' Abre la Base de Datos
        If DB.OpenDB() = False Then Return ERR_CANT_OPEN_BD
' creamos un nuevo template
        template.Size = 0
' Creamos La Imagen
        raw.img = Nothing
        raw.width = 0
        raw.height = 0
' Guardamos el Resultado de la Inicializacion del Lector
        err = _GrFingerX.Initialize()
' Si es menor que 0 es porque ocurrio un error con el lector
    sea de lectura y/o de conexion
        If err < 0 Then Return err
        Return _GrFingerX.CapInitialize()
    End Function


' Método que Finaliza la Captura y el Uso del Lector de
    Huellas
    Public Sub FinalizeGrFinger()
        _GrFingerX.Finalize()
        _GrFingerX.CapFinalize()
    End Sub

' Obtiene la Imagen del Lector y la Muestra en el PictureBox
    Public Sub PrintBiometricDisplay(ByVal biometricDisplay As Boolean, ByVal context As Integer)
' Maneja la Imagen de Un Dedo
        Dim handle As System.Drawing.Image = Nothing
' HDC de la Pantalla
        Dim hdc As Integer = GetDC(0)

        If biometricDisplay Then
' Obtiene la Imagen con la Informacion Biométrica
            _GrFingerX.BiometricDisplay(template.tpt, raw.img, raw.width, _
		raw.height, raw.res, hdc, _
	 	handle, context)
        Else
            _GrFingerX.CapRawImageToHandle(raw.img, raw.width, raw.height, hdc, handle)
        End If


' Dibuja la Imagen Obtenida en el PictureBox
        If Not (handle Is Nothing) Then
            _pbPic.Image = handle
            _pbPic.Update()
        End If
' Quitamos de Memoria El HDC de la Pantalla Obtenido
        ReleaseDC(0, hdc)
    End Sub


' Guarda la Data de la Huella Digital Obtenida en la Base
    de Datos
    Public Function Enroll(ByVal contded As Integer, ByVal Cedula As String) As Integer
' Verifica si la Data de la Huella Obtenida es Valida
        If TemplateIsValid() Then


' Guarda la Huella digital Obtenida, con la Cedula de la
    Persona y Genera un ID para la Huella
            Return DB.AddTemplate(template, Cedula, contded)
        Else
            Return -1
        End If
    End Function

    Function ExtractTemplate() As Integer
        Dim ret As Integer
        template.Size = template.tpt.Length
        ret = _GrFingerX.Extract(raw.img, raw.width, raw.height, raw.res, template.tpt, _
 template.Size, GRConstants.GR_DEFAULT_CONTEXT)
        If ret < 0 Then template.Size = 0
        Return ret
    End Function

    Public Function Identify(ByRef score As Integer) As Integer
        Dim ret As Integer
        Dim i As Integer
        If Not TemplateIsValid() Then Return ERR_INVALID_TEMPLATE
        ret = _GrFingerX.IdentifyPrepare(template.tpt, GRConstants.GR_DEFAULT_CONTEXT)
        If ret < 0 Then Return ret
        Dim templates As TTemplates() = DB.getTemplates()
        For i = 1 To templates.Length - 1
            If Not (templates(i).template Is Nothing) Then
                ret = _GrFingerX.Identify(templates(i).template.tpt, score, _
			GRConstants.GR_DEFAULT_CONTEXT)
            End If
            If ret = GRConstants.GR_MATCH Then
                Return templates(i).ID
            End If
            If ret < 0 Then Return ret
        Next
        Return GRConstants.GR_NOT_MATCH
    End Function

    Public Function Verify(ByVal id As Integer, ByRef score As Integer) As Integer
        Dim tptref As Byte()
        If Not (TemplateIsValid()) Then Return ERR_INVALID_TEMPLATE
        tptref = DB.getTemplate(id)
        If tptref Is Nothing Then Return ERR_INVALID_ID
        Return _GrFingerX.Verify(template.tpt, tptref, score, GRConstants.GR_DEFAULT_CONTEXT)
    End Function

    Public Function ObtenerNombre(ByVal Cedula As String) As String
        Dim NomComp As String
        Dim cn As New System.Data.SqlClient.SqlConnection(My.Settings.AccesoConnectionString)
        Dim cmd As New System.Data.SqlClient.SqlCommand( _
		"Select Nombre, Apellido From Empleados Where Cedula='" _ 
		& Cedula & "'", cn)
        cn.Open()
        Dim rd As System.Data.SqlClient.SqlDataReader = cmd.ExecuteReader()
        If rd.Read Then
            NomComp = Trim(rd.Item("Nombre").ToString) & " " & Trim(rd.Item("Apellido").ToString)
            Return NomComp
        Else
            Return ""
        End If
        cn.Close()
    End Function
 

End Class

Bueno., espero que sea de su utilidad éste artículo....

Aqui les dejo algunas de las pantallas para que se hagan una idea de lo que les estoy presentando., el sistema es completamente funcianal y de libre distribución:

1.- Pantalla de Bienvenida...

2.- Pantalla de Menu Principal...

3.- Pantalla de Chequeo del Sistema...

4.- Pantalla de registro de Empleados...

5.- Pantalla de Modificacion de Empleados...

6.- Pantalla de Algunos de los Reportes...

7.- Pantalla de Control de Documentos del Personal...

8.- Pantalla de Solicitudes de Permisos...

Anímense a bajar el Código y ayudarme también a mejorar lo que ya tengo.
Suerte.....


Espacios de nombres usados en el código de este artículo:

System.Data
System.Data.SqlClient
GrFingerXLib
System.Runtime.InteropServices

 


Código de ejemplo (ZIP):

 

Fichero con el código de ejemplo: IvanElias_ControlAcceso_VB.zip - 1.45 MB

(MD5 checksum: AEA7CFC718C9DD4E14101F61986057FC)

 


ir al índice principal del Guille