記一次曙光易通指靜脈開發中遇到的坑


前述: 公司是做社保,醫療行業的,接了個單子,制作生存認證項目,使用曙光易通的指靜脈儀,然后誕生了n多需求,在前期已完成electron的ffi模塊來調用dll,現把這兩周遇到的坑記錄如下

 

需求1:指靜脈過程中不要彈框

需求2:兼容知能易通的指靜脈儀(注:知能易通是曙光易通的舊版本,現早不提供)

 

需求1的解決:

  先請求廠家幫助提供無彈框的dll,結果又幾率仍然彈框,所以換成我用java來寫

  需求如下:1.程序檢測窗口出現拍攝登錄圖像等字樣,發送回車命令 2.隨客戶端啟動 

       使用的jna框架調用user32命令,在執行中可以加入循環,判斷electron標題,如果標題不存在,即關閉,結束循環,關閉程序

package yinhai.com;

import com.sun.jna.Native;

public interface User32 extends W32API {
    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
    
    boolean ShowWindow(HWND hWnd, int nCmdShow);
    
    boolean SetForegroundWindow(HWND hWnd);
    
    HWND FindWindow(String winClass, String title);
    
    HWND FindWindow(int winClass, String title);
    
    HWND FindWindowEx(HWND hWnd, HWND childWnd, int wParam, int lParam);
    
    HWND FindWindowEx(HWND hWnd, int childWnd, int wParam, int lParam);
    
    boolean PostMessage(HWND hWnd, Integer Msg, Integer wParam, Integer lParam);
    
    boolean PostMessage(HWND hWnd, int Msg, int wParam, int lParam);
    
    boolean PostMessage(HWND hWnd, String Msg, int wParam, int lParam);
    
    boolean PostMessage(HWND hWnd, String Msg, String wParam, String lParam);
    
    boolean PostMessage(HWND hWnd, int Msg, String wParam, String lParam);
    
    boolean PostMessage(HWND hWnd, int Msg, String wParam, int lParam);
    
    boolean PostMessage(HWND hWnd, String Msg, String wParam, int lParam);
    
    void keybd_event(String bVk, String bScan, String dwFlags, String dwExtralnfo);
    
    void keybd_event(int bVk, String bScan, String dwFlags, String dwExtralnfo);
    
    void keybd_event(String bVk, int bScan, int dwFlags, int dwExtralnfo);
    
    void keybd_event(int bVk, int bScan, int dwFlags, int dwExtralnfo);
    
    void keybd_event(int bVk, int bScan, String dwFlags, int dwExtralnfo);
    
    void keybd_event(String bVk, int bScan, String dwFlags, int dwExtralnfo);
    
    boolean SendMessage(HWND hWnd, Integer Msg, Integer wParam, Integer lParam);
    
    boolean SendMessage(HWND hWnd, int Msg, int wParam, int lParam);
    
    boolean SendMessage(HWND hWnd, String Msg, int wParam, int lParam);
    
    boolean SendMessage(HWND hWnd, String Msg, String wParam, String lParam);
    
    boolean SendMessage(HWND hWnd, int Msg, String wParam, String lParam);
    
    boolean SendMessage(HWND hWnd, int Msg, String wParam, int lParam);
    
    boolean SendMessage(HWND hWnd, String Msg, String wParam, int lParam);
}
定義user32dll接口
package yinhai.com;

import java.util.HashMap;
import java.util.Map;
import com.sun.jna.FromNativeContext;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;

@SuppressWarnings({ "unchecked", "serial" })
public interface W32API extends StdCallLibrary {
    Map UNICODE_OPTIONS = new HashMap() {
        private static final long serialVersionUID = 1L;
        {
            put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
            put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
        }
    };
    Map ASCII_OPTIONS = new HashMap() {
        {
            put(OPTION_TYPE_MAPPER, W32APITypeMapper.ASCII);
            put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.ASCII);
        }
    };
    Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS;
    
    public static class HANDLE extends PointerType {
        public Object fromNative(Object nativeValue, FromNativeContext context) {
            Object o = super.fromNative(nativeValue, context);
            if (INVALID_HANDLE_VALUE.equals(o))
                return INVALID_HANDLE_VALUE;
            return o;
        }
    }
    
    public static class HWND extends HANDLE {
    }
    
    HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
        {
            super.setPointer(Pointer.createConstant(-1));
        }
        
        public void setPointer(Pointer p) {
            throw new UnsupportedOperationException("Immutable reference");
        }
    };
}
W32API
package yinhai.com;

import java.io.IOException;

import javax.swing.JOptionPane;

public class ListenerWindow {
    
    public static void main(String[] args) {
        

        W32API.HWND targetHwnd=null;
        
        W32API.HWND hwnd;
        W32API.HWND ytjHwnd;
        W32API.HWND ytjErrorHwnd;
        W32API.HWND ytjFallHwnd;
        
        // 循環監聽一體機窗口
        boolean ytjState = true;
        
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        while (ytjState) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            hwnd = User32.INSTANCE.FindWindow(0, "拍攝登錄圖像");
            ytjHwnd = User32.INSTANCE.FindWindow(0, "生存認證指靜脈離線采集程序");
            ytjErrorHwnd = User32.INSTANCE.FindWindow(0, "Sugon");
            ytjFallHwnd = User32.INSTANCE.FindWindow(0, "信息提示");
            
            // W32API.HWND hwnd = User32.INSTANCE.FindWindow(0, "Sugon");
            // W32API.HWND childHwnd = User32.INSTANCE.FindWindowEx(hwnd, 0, 0,
            // 0);
            // User32.INSTANCE.SetForegroundWindow(hwnd);
            /*
             * for (int i = 0; i < 100; i++) { // keyPress(82); //
             * //User32.INSTANCE.PostMessage(hwnd, // 82, 0,0);
             * backKeyPress(childHwnd, 82); }
             */
            // System.out.println("運行中");
            if (hwnd != null||ytjErrorHwnd != null||ytjFallHwnd != null) {
                if(hwnd!=null) {
                    targetHwnd=hwnd;
                    hwnd=null;
                }else if(ytjErrorHwnd!=null){
                    targetHwnd=ytjErrorHwnd;
                    ytjErrorHwnd=null;
                }else if(ytjFallHwnd!=null){
                    targetHwnd=ytjFallHwnd;
                    ytjFallHwnd=null;
                }
                User32.INSTANCE.ShowWindow(targetHwnd, 9);
                User32.INSTANCE.SetForegroundWindow(targetHwnd);
                // 發送回車命令
                User32.INSTANCE.PostMessage(targetHwnd, 256, 0xD, 0);
            }
            
            /*//關閉
            if (ytjHwnd == null) {
                // System.out.println("no exe");
                //JOptionPane.showMessageDialog(null, "輔助采集程序關閉", "指靜脈離線程序", JOptionPane.ERROR_MESSAGE);
                ytjState = false;
            }*/
            
            /*
             * if (hwnd != null) { User32.INSTANCE.ShowWindow(hwnd, 9);
             * User32.INSTANCE.SetForegroundWindow(hwnd); } else { try {
             * System.out.println(" can't find the window !!");
             * Runtime.getRuntime().exec("NotePad.exe"); } catch (IOException e)
             * { e.printStackTrace(); } }
             */
        }
    }
    
    public static void backKeyPress(W32API.HWND hwnd, int keyNum) {
        User32.INSTANCE.PostMessage(hwnd, 256, keyNum, 0);
    }
    
    public static void backKeyRelease(W32API.HWND hwnd, int keyNum) {
        User32.INSTANCE.PostMessage(hwnd, 257, keyNum, 0);
    }
    
    public static void keyPress(int keyNum) {
        User32.INSTANCE.keybd_event(keyNum, 0, 0, 0);
        User32.INSTANCE.keybd_event(keyNum, 0, "KEYEVENTF_KEYUP", 0);
    }
}
主方法

接着為了擴展項目通用性,把java18的32和64位的jre包提取出來,然后寫了一個bat隱藏啟動(如下圖)

然后在electron的main.js中讓在加載中調用bat

//加載cmd命令
var execState=new Boolean(true);
const exec = require('child_process');

//在基本命令加載完后再啟動cmd加載
app.on('will-finish-launching',() => {
    if(execState==true){
    runExec(execState); // 生效啦,可以做些什么執行一種相對的同步狀態,例如判斷輸出內容到什么了    
    execState=false;
    }    
});


// 任何你期望執行的cmd命令,ls都可以
let cmdStr = "start.bat";//'./你的可執行程序名稱 -p 需要輸入密碼的話'
// 執行cmd命令的目錄,如果使用cd xx && 上面的命令,這種將會無法正常退出子進程 
let cmdPath =  process.cwd()+"\\resources\\app\\jar";
// 子進程名稱
let workerProcess

function runExec() {
        exec.execFile(cmdStr, [], {cwd:cmdPath}, function(error, stdout, stderr) {
            console.log(error);
            console.log(stdout);
        });
main.js 的主要修改項

 

接下來講講知能易通和曙光易通指靜脈儀的坑

  首先要知道知能易通和曙光易通是一個公司,曙光易通是知能易通的升級版

直接說解決方法:

  1.找廠家要最新版的驅動,我用的是5.0.0.3NoP-AC,然后必須連上曙光易通的靜脈儀,卸載舊驅動,安裝新驅動

  2.使用CoorperateRegistTool.exe給程序生成reg文件

  3.如果電腦是32位,需用管理員身份運行reg.reg,如果電腦是64位,

  需用管理員運行 C:\Windows\SysWOW64目錄下的cmd.exe,輸入 reg import 路徑\reg.reg

  4.從驅動的安裝demo下把dll拷出來,調用dll獲取控件版本返回的是-1,但其實是獲取了,獲得的值與頁面調html調ocx控件返回的值不同

  5.然后除了獲取指紋模板其他方法可以不變,方法如下圖

  盡管開發完成,但是在使用過程中仍然能明顯感到使用的吃力,如1:N認證時返回255,無法確定最佳手指位置,最后作為了認證失敗處理

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM