Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检测控制台应用程序外部的指纹读取器输入_C#_Wcf_Windows 8_Msmq_Biometrics - Fatal编程技术网

C# 检测控制台应用程序外部的指纹读取器输入

C# 检测控制台应用程序外部的指纹读取器输入,c#,wcf,windows-8,msmq,biometrics,C#,Wcf,Windows 8,Msmq,Biometrics,因此,我需要制作一个Metro GUI应用程序,使用外部指纹读取器进行用户识别 我已经在C++中做了一个DLL,所以我可以调用一个我在C引用引用DLL的方法中调用的方法: CAPUTSRAMP()/CUL>。CaptureSample()方法为我提供了一个字节数组,表示扫描的指纹(指纹读取器的灰度图像)。到目前为止还不错。其方法是使用Microsoft生物识别框架访问读卡器,等待读卡器检测到手指放在上面,然后将扫描指纹的数据发送回 这一切都很好。但是有一个缺点:我必须运行我作为管理员制作的任何应

因此,我需要制作一个Metro GUI应用程序,使用外部指纹读取器进行用户识别

我已经在C++中做了一个DLL,所以我可以调用一个我在C引用引用DLL的方法中调用的方法:<代码> CAPUTSRAMP()/CUL>。
CaptureSample()
方法为我提供了一个字节数组,表示扫描的指纹(指纹读取器的灰度图像)。到目前为止还不错。其方法是使用Microsoft生物识别框架访问读卡器,等待读卡器检测到手指放在上面,然后将扫描指纹的数据发送回

这一切都很好。但是有一个缺点:我必须运行我作为管理员制作的任何应用程序才能使用框架。这也是为什么我不能从Web服务运行框架的原因,因为Web服务是作为网络用户或类似用户运行的,这使得库在尝试使用它时拒绝任何访问。所以我必须制作一个额外的控制台程序来运行它

现在事情变得棘手了。为了使指纹读取器与Windows Metro GUI应用程序一起工作,您必须以管理员身份运行该应用程序。这是不可能的,因为所有Metro GUI应用程序都在沙箱中运行。我必须制作一个外部控制台应用程序,调用应用程序的DLL功能,然后将结果发送回应用程序

让事情变得更复杂的是,我发现.NET的Windows Phone子集没有MSMQ,而MSMQ本来可以很好地使用。因此,我创建了Metro应用程序需要调用的本地WCF服务,然后WCF服务通过MSMQ调用控制台程序,并在Metro GUI应用程序从控制台应用程序接收信息时将其发送回Metro GUI应用程序

到目前为止还不错。理论上。我在这个过程中遇到了一个问题,因为控制台应用程序确实在运行,并且在被询问时可以进行扫描。但当我扫描我的手指时,什么也没发生。控制台需要聚焦才能工作,这是不可能的,因为该应用程序就像一个信息亭一样运行,除非进行维护,否则不应该离开Metro GUI应用程序

我研究过各种检测C#应用程序外部键盘输入的解决方案,但我认为这不适用于指纹读取器,或者如果指纹读取器适用,我不知道该怎么做。有什么建议吗

为了更好地理解,我附带了一个工作流程图。(如果有人好奇,这是一款P5100 Zvetcobiometrics指纹读取器):


因此,我在Windows窗体中遇到了类似的问题,但与您描述的问题不完全相同

我知道我的解决方案对你来说不是预先编码好的轻松日解决方案,但我觉得经过一些小的修改,几年前我克服的一个障碍可能对你有用。如果你认为我的解决方案对你有帮助,我可以寄给你任何缺失的部分

我创建了一个利用条形码扫描仪的库存管理系统,我决定实现在某些C++类中通过编组来处理设备输入的能力,而不需要使用诸如文本框之类的输入控件。我需要应用程序能够处理条形码输入并做出决策,而无需任何额外的用户交互或需求。扫描一下就走。直接使用键盘/HID设备的输入是我认为此解决方案适合您问题的原因

在测试我编写的应用程序时,我能够进入一个全屏游戏,并且仍然能够像在windows窗体清单应用程序中预期的那样使用条形码扫描仪。这一功能在控制台环境中应该同样有效,因为控制台应用程序在后台时不会停止。您甚至可以将它设置为NT权限,并防止它在作为服务运行时显示在桌面上,并且它仍应继续运行

我所做的是使用Win32API通过设备进行反映,将设备与通过应用程序(用户选择)指定的设备进行匹配,并基本上为该特定设备建立了侦听器

您可以使用控制台应用程序触发指纹传感器,方法是将控制台应用程序作为本地服务帐户运行,或以编程方式获得必要的授权(这将允许您在提升权限下运行它,而无需UAC人员妨碍您)然后在你的metro应用程序中使用它来读取设备发送的输入

下面是一些代码文件,用于我所描述的内容,并已修改为特定于我的条形码扫描仪功能

同样,如果你想看到任何遗失的物品,请私下联系我

PS:从技术上讲,这可能被用作拦截密钥之类的黑客,因此我将为您提供一份免责声明,供您自行决定使用,我对愚蠢的人可能使用此代码所做的任何事情概不负责

条形码扫描程序ListenerInterophelper.h:

#include <winuser.h>

BEGIN_INTEROP_NAMESPACE

using namespace System;
using namespace System::Collections::Generic;
using namespace HFSLIB::Barcode;
using namespace HFSLIB::Barcode::Interop;
using namespace HFSLIB::Barcode::Infrastructure::BarcodeScannerListener;

/// <summary>
/// Provides some helper methods that help the BarcodeScannerListener use native
/// Windows APIs without resorting to P/Invoking from C#.
/// </summary>
public ref class BarcodeScannerListenerInteropHelper
{
    public:
        /// <summary>
        /// Returns a dictionary of barcode device handles to information about
        /// the device.
        /// </summary>
        /// <param name="hardwareIds">The enumerable of hardware IDs to filter by.</param>
        /// <returns>The device handle-to-information mapping of the filtered hardware IDs.</returns>
        Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ InitializeBarcodeScannerDeviceHandles(
            IEnumerable<String^>^ hardwareIds);

        /// <summary>
        /// Registers ourselves to listen to raw input from keyboard-like devices.
        /// </summary>
        /// <param name="hwnd">the handle of the form that will receive the raw
        /// input messages</param>
        /// <exception cref="InvalidOperationException">if the call to register with the
        /// raw input API fails for some reason</exception>
        void HookRawInput(IntPtr hwnd);

        /// <summary>
        /// Gets information from a WM_INPUT message.
        /// </summary>
        /// <param name="rawInputHeader">The LParam from the WM_INPUT message.</param>
        /// <param name="deviceHandle">[Out] The device handle that the message came from.</param>
        /// <param name="handled">[Out] True if the message represents a keystroke from that device.</param>
        /// <param name="buffer">[Out] If handled is true, this contains the characters that the keystroke represents.</param>
        void GetRawInputInfo(
            IntPtr rawInputHeader, 
            IntPtr% deviceHandle, 
            bool% handled,
            String^% buffer);
    private:
        /// <summary>
        /// Converts a native raw input type into our version.
        /// </summary>
        /// <param name="rawInputType">The raw input type.</param>
        /// <returns>Our version of the type.</returns>
        static BarcodeScannerDeviceType GetBarcodeScannerDeviceType(DWORD rawInputType);
};

END_INTEROP_NAMESPACE
#包括
开始\u互操作\u命名空间
使用名称空间系统;
使用命名空间System::Collections::Generic;
使用名称空间HFSLIB::Barcode;
使用名称空间HFSLIB::Barcode::Interop;
使用名称空间HFSLIB::Barcode::Infrastructure::BarcodeScannerListener;
/// 
///提供一些帮助器方法,帮助BarcodeScannerListener使用本机
///Windows API,而无需从C#调用P/Invoking。
/// 
公共引用类条形码扫描程序ListenerInterophelper
{
公众:
/// 
///返回条形码设备句柄的字典,以获取有关
///这个装置。
/// 
///要筛选的硬件ID的可枚举项。
///设备句柄到已过滤硬件ID的信息映射。
字典^InitializeBarcodeScannerDeviceHandles(
IEnumerable^ hardwareIds);
/// 
///登记我们自己去听
#include "BarcodeScannerListenerInteropHelper.h"
using namespace System::ComponentModel;

BEGIN_INTEROP_NAMESPACE

/// <summary>
/// Gets information from a WM_INPUT message.
/// </summary>
/// <param name="rawInputHeader">The LParam from the WM_INPUT message.</param>
/// <param name="deviceHandle">[Out] The device handle that the message came from.</param>
/// <param name="handled">[Out] True if the message represents a keystroke from that device.</param>
/// <param name="buffer">[Out] If handled is true, this contains the characters that the keystroke represents.</param>
void BarcodeScannerListenerInteropHelper::GetRawInputInfo(
    IntPtr rawInputHeader,
    IntPtr% deviceHandle, 
    bool% handled,
    String^% buffer)
{
    UINT cbSize;
    HRAWINPUT hRawInput;

    hRawInput = (HRAWINPUT)rawInputHeader.ToPointer();
    if (GetRawInputData(hRawInput, RID_INPUT, NULL, &cbSize, sizeof(RAWINPUTHEADER)) == 0)
    {
        RAWINPUT* raw;

        raw = (RAWINPUT*)malloc(cbSize);

        if (GetRawInputData(hRawInput, RID_INPUT, raw, &cbSize, sizeof(RAWINPUTHEADER)) == cbSize)
        {
            deviceHandle = IntPtr(raw->header.hDevice);
            handled = raw->header.dwType == RIM_TYPEKEYBOARD &&
                raw->data.keyboard.Message == WM_KEYDOWN;

            if (handled)
            {
                BYTE state[256];

                // Force the keyboard status cache to update
                GetKeyState(0);

                // Note: GetKeyboardState only returns valid state when
                // the application has focus -- this is why we weren't
                // getting shift keys when the application was not focused
                if (GetKeyboardState(state))
                {
                    WCHAR unmanagedBuffer[64];

                    if (ToUnicode(raw->data.keyboard.VKey,
                            raw->data.keyboard.MakeCode,
                            state,
                            unmanagedBuffer,
                            64,
                            0) > 0)
                    {
                        buffer = gcnew String(unmanagedBuffer);
                    }
                }
            }
        }

        free(raw);
    }
}

/// <summary>
/// Registers ourselves to listen to raw input from keyboard-like devices.
/// </summary>
/// <param name="hwnd">the handle of the form that will receive the raw
/// input messages</param>
/// <exception cref="InvalidOperationException">if the call to register with the
/// raw input API fails for some reason</exception>
void BarcodeScannerListenerInteropHelper::HookRawInput(IntPtr hwnd)
{
    RAWINPUTDEVICE rid[1];

    rid[0].dwFlags = 0;
    rid[0].hwndTarget = (HWND)hwnd.ToPointer();
    rid[0].usUsage = 0x06;     // Keyboard Usage ID
    rid[0].usUsagePage = 0x01; // USB HID Generic Desktop Page

    if (!RegisterRawInputDevices(rid, 1, sizeof(RAWINPUTDEVICE)))
    {
        InvalidOperationException^ e;

        e = gcnew InvalidOperationException(
            "The barcode scanner listener could not register for raw input devices.",
            gcnew Win32Exception());
        throw e;
    }
}

/// <summary>
/// Returns a dictionary of barcode device handles to information about
/// the device.
/// </summary>
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ BarcodeScannerListenerInteropHelper::InitializeBarcodeScannerDeviceHandles(IEnumerable<String^>^ hardwareIds)
{
    Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ devices;
    UINT uiNumDevices;
    UINT cbSize;

    devices = gcnew Dictionary<IntPtr, BarcodeScannerDeviceInfo^>();
    uiNumDevices = 0;
    cbSize = sizeof(RAWINPUTDEVICELIST);

    if (GetRawInputDeviceList(NULL, &uiNumDevices, cbSize) != -1)
    {
        PRAWINPUTDEVICELIST pRawInputDeviceList;

        if (pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(cbSize * uiNumDevices))
        {
            if (GetRawInputDeviceList(pRawInputDeviceList, &uiNumDevices, cbSize) != -1)
            {
                for (UINT i = 0; i < uiNumDevices; ++i)
                {
                    UINT pcbSize;
                    RAWINPUTDEVICELIST rid;

                    rid = pRawInputDeviceList[i];

                    if (GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, NULL, &pcbSize) >= 0 &&
                        pcbSize > 0)
                    {
                        WCHAR* deviceName;

                        deviceName = (WCHAR*)malloc(sizeof(WCHAR) * (pcbSize + 1));
                        if (GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, deviceName, &pcbSize) >= 0)
                        {
                            bool add;
                            IntPtr deviceHandle;
                            BarcodeScannerDeviceInfo^ info;
                            String^ managedDeviceName;

                            add = false;
                            deviceHandle = IntPtr(rid.hDevice);
                            managedDeviceName = gcnew String(deviceName);

                            for each (String^ hardwareId in hardwareIds)
                            {
                                if (managedDeviceName->IndexOf(hardwareId, StringComparison::OrdinalIgnoreCase) >= 0)
                                {
                                    add = true;
                                    break;
                                }
                            }

                            if (add)
                            {
                                info = gcnew BarcodeScannerDeviceInfo(
                                    managedDeviceName,
                                    BarcodeScannerListenerInteropHelper::GetBarcodeScannerDeviceType(rid.dwType),
                                    deviceHandle);

                                devices->Add(deviceHandle, info);
                            }
                        }

                        free(deviceName);
                    }
                }
            }

            free(pRawInputDeviceList);
        }
    }

    return devices;
}

/// <summary>
/// Converts a native raw input type into our version.
/// </summary>
/// <param name="rawInputType">The raw input type.</param>
/// <returns>Our version of the type.</returns>
BarcodeScannerDeviceType BarcodeScannerListenerInteropHelper::GetBarcodeScannerDeviceType(DWORD rawInputType)
{
    BarcodeScannerDeviceType type;

    switch (rawInputType)
    {
        case RIM_TYPEHID:
            type = BarcodeScannerDeviceType::HumanInterfaceDevice;
            break;
        case RIM_TYPEKEYBOARD:
            type = BarcodeScannerDeviceType::Keyboard;
            break;
        default:
            type = BarcodeScannerDeviceType::Unknown;
            break;
    }

    return type;
}

END_INTEROP_NAMESPACE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
using HFSLIB.Barcode.Infrastructure.BarcodeScannerListener;
using HFSLIB.Barcode.Interop;

namespace HFSLIB.Barcode
{
/// <summary>
/// This class uses Windows's native Raw Input API to listen for input from
/// a certain set of barcode scanners and devices. This way, the application
/// can receive input from a barcode scanner without the user having to
/// worry about whether or not a certain text field has focus, which was a
/// big problem
/// </summary>
public class BarcodeScannerListener : NativeWindow
{
    /// <summary>
    /// A mapping of device handles to information about the barcode scanner
    /// devices.
    /// </summary>
    private Dictionary<IntPtr, BarcodeScannerDeviceInfo> devices;

    /// <summary>
    /// The WM_KEYDOWN filter.
    /// </summary>
    private BarcodeScannerKeyDownMessageFilter filter;

    /// <summary>
    /// The barcode currently being read.
    /// </summary>
    private StringBuilder keystrokeBuffer;

    /// <summary>
    /// The interop helper.
    /// </summary>
    private BarcodeScannerListenerInteropHelper interopHelper =
        new BarcodeScannerListenerInteropHelper();

    /// <summary>
    /// Event fired when a barcode is scanned.
    /// </summary>
    public event EventHandler BarcodeScanned;

    /// <summary>
    /// Attaches the listener to the given form.
    /// </summary>
    /// <param name="form">The form to attach to.</param>
    public void Attach(Form form)
    {
        IntPtr hwnd;

        if (form == null)
        {
            throw new ArgumentNullException("form");
        }

        hwnd = form.Handle;

        this.keystrokeBuffer = new StringBuilder();

        this.InitializeBarcodeScannerDeviceHandles();
        this.interopHelper.HookRawInput(hwnd);
        this.HookHandleEvents(form);

        this.AssignHandle(hwnd);

        this.filter = new BarcodeScannerKeyDownMessageFilter();
        Application.AddMessageFilter(this.filter);
    }

    /// <summary>
    /// Hook into the form's WndProc message. We listen for WM_INPUT and do
    /// special processing on the raw data.
    /// </summary>
    /// <param name="m">the message</param>
    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case NativeMethods.WM_INPUT:
                if (this.ProcessRawInputMessage(m.LParam))
                {
                    this.filter.FilterNext = true;
                }

                break;
        }

        base.WndProc(ref m);
    }

    /// <summary>
    /// Fires the barcode scanned event.
    /// </summary>
    /// <param name="deviceInfo">information about the device that generated
    /// the barcode</param>
    private void FireBarcodeScanned(BarcodeScannerDeviceInfo deviceInfo)
    {
        string barcode;
        EventHandler handler;

        barcode = this.keystrokeBuffer.ToString();

        if (barcode != null && barcode.Length > 0)
        {
            handler = this.BarcodeScanned;

            this.keystrokeBuffer = new StringBuilder();

            if (handler != null)
            {
                handler(this, new BarcodeScannedEventArgs(barcode, deviceInfo));
            }
        }
    }

    /// <summary>
    /// Hooks into the form's HandleCreated and HandleDestoryed events
    /// to ensure that we start and stop listening at appropriate times.
    /// </summary>
    /// <param name="form">the form to listen to</param>
    private void HookHandleEvents(Form form)
    {
        form.HandleCreated += this.OnHandleCreated;
        form.HandleDestroyed += this.OnHandleDestroyed;
    }

    /// <summary>
    /// Initializes the barcode scanner device handles.
    /// </summary>
    private void InitializeBarcodeScannerDeviceHandles()
    {
        BarcodeScannerListenerConfigurationSection config;
        BarcodeScannerListenerConfigurationElementCollection hardwareIdsConfig;
        IEnumerable<string> hardwareIds;

        config = BarcodeScannerListenerConfigurationSection.GetConfiguration();
        hardwareIdsConfig = config.HardwareIds;
        hardwareIds = from hardwareIdConfig in hardwareIdsConfig.Cast<BarcodeScannerListenerConfigurationElement>()
                      select hardwareIdConfig.Id;

        this.devices = this.interopHelper.InitializeBarcodeScannerDeviceHandles(hardwareIds);
    }

    /// <summary>
    /// When the form's handle is created, let's hook into it so we can see
    /// the WM_INPUT event.
    /// </summary>
    /// <param name="sender">the form whose handle was created</param>
    /// <param name="e">the event arguments</param>
    private void OnHandleCreated(object sender, EventArgs e)
    {
        this.AssignHandle(((Form)sender).Handle);
    }

    /// <summary>
    /// When the form's handle is destroyed, let's unhook from it so we stop
    /// listening and allow the OS to free up its resources.
    /// </summary>
    /// <param name="sender">the form whose handle was destroyed</param>
    /// <param name="e">the event arguments</param>
    private void OnHandleDestroyed(object sender, EventArgs e)
    {
        this.ReleaseHandle();
    }

    /// <summary>
    /// Process the given WM_INPUT message.
    /// </summary>
    /// <param name="rawInputHeader">the rawInputHeader of the message</param>
    /// <returns>whether or not the keystroke was handled</returns>
    private bool ProcessRawInputMessage(IntPtr rawInputHeader)
    {
        BarcodeScannerDeviceInfo deviceInfo;
        bool handled;
        bool keystroke;
        string localBuffer;
        IntPtr rawInputDeviceHandle;

        handled = false;
        keystroke = false;
        localBuffer = string.Empty;
        rawInputDeviceHandle = IntPtr.Zero;

        this.interopHelper.GetRawInputInfo(
            rawInputHeader,
            ref rawInputDeviceHandle,
            ref keystroke,
            ref localBuffer);

        if (this.devices.TryGetValue(rawInputDeviceHandle, out deviceInfo) && keystroke)
        {
            handled = true;

            if (localBuffer.Length == 1 && localBuffer[0] == 0xA)
            {
                this.FireBarcodeScanned(deviceInfo);
            }
            else
            {
                this.keystrokeBuffer.Append(localBuffer);
            }
        }

        return handled;
    }
}
}