无法弄清楚如何检查是否存在生物特征

时间:2012-05-08 17:34:15

标签: c# pinvoke guid device wmi-query

在工作中我们制作自己的平板电脑。一些平板电脑具有指纹生物识别技术,有些则没有。有时技术会忘记将其插入。我还没有找到一种方法来检查该设备(或任何此类设备)是否存在。

我的第一种方法是使用GUID作为{53D29EF7-377C-4D14-864B-EB3A85769359}的生物识别。我会在hklm\system\currontcontrolset\control\class的注册表中搜索并检查该密钥是否存在。

这不起作用,因为即使您从未安装过生物识别系统,Windows 7似乎也存在该密钥。它在XP中运行,但我只是在一个曾经生物识别的单元上再试过但是我把它拿出来并且那个键仍然存在。

关于这个问题最困难的部分是我必须使用Windows 7,7嵌入式,xp和xp嵌入式。

下一个想法是使用WMI,但我找不到正确的类来调用它是否存在。

然后我找到了biometric.dll,但这只适用于Windows 7。

有时找到问题的常见解决方案并不总是那么容易。我正在用C#做这个项目,但是我愿意把它转换成任何语言。

我应该开始寻找任何想法吗?

1 个答案:

答案 0 :(得分:3)

在Joshua Drake的帮助下,他给了我一个关于如何解决问题的精彩链接,这些都是我的结果:

我要修改的代码是专门用于查找特定GUID而查找第一个代码的代码。我从有关如何禁用设备的文章中对其进行了调整,尽管此代码不会禁用任何仅仅检查存在的内容。

    public static bool IsDevicePresent(string guid)
    {
        var info = IntPtr.Zero;
        var NullGuid = new Guid(guid);
        try
        {
            info = SetupDiGetClassDevsW(ref NullGuid,null,IntPtr.Zero,DIGCF_PRESENT);
            CheckError("SetupDiGetClassDevs");
            var devdata = new SP_DEVINFO_DATA();
            devdata.cbSize = (UInt32)Marshal.SizeOf(devdata);
            // Get first device matching device criterion.
            SetupDiEnumDeviceInfo(info,0,out devdata);
            // if no items match filter, throw
            if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
                CheckError("No device found matching filter.", 0xcffff);
            CheckError("SetupDiEnumDeviceInfo");
        }
        catch
        {
            return false;
        }
        finally
        {
            if (info != IntPtr.Zero)
                SetupDiDestroyDeviceInfoList(info);
        }
        return true;
    }

    private static void CheckError(string message, int lasterror = -1)
    {
        int code = lasterror == -1 ? Marshal.GetLastWin32Error() : lasterror;
        if (code != 0)
            throw new ApplicationException(String.Format("Error disabling hardware device (Code {0}): {1}",code, message));
    } 

    [DllImport("setupapi.dll", SetLastError = true)]
    private static extern IntPtr SetupDiGetClassDevsW([In] ref Guid ClassGuid,[MarshalAs(UnmanagedType.LPWStr)]string Enumerator,IntPtr parent,UInt32 flags);

    [DllImport("setupapi.dll", SetLastError = true)]
    private static extern bool SetupDiDestroyDeviceInfoList(IntPtr handle);

    [DllImport("setupapi.dll", SetLastError = true)]
    private static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet,UInt32 memberIndex,[Out] out SP_DEVINFO_DATA deviceInfoData);  
    //used to find device info from device manager
    [StructLayout(LayoutKind.Sequential)]
    private struct SP_DEVINFO_DATA
    {
        public UInt32 cbSize;
        public Guid classGuid;
        public UInt32 devInst;
        public IntPtr reserved;
    } 
    private const uint DIGCF_PRESENT = 2;
    private const uint ERROR_INVALID_DATA = 13;
    private const uint ERROR_NO_MORE_ITEMS = 259;
    private const uint ERROR_ELEMENT_NOT_FOUND = 1168;

这是一个简单的单元测试,证明它适用于第一个设备

    [Test]
    public void TestDevicePresent()
    {
        var bluetoothClassGuid = "e0cbf06c-cd8b-4647-bb8a-263b43f0f974";
        var biometricClassGuid = "53D29EF7-377C-4D14-864B-EB3A85769359";
        var cdromdrivClassGiud = "4d36e965-e325-11ce-bfc1-08002be10318";
        Assert.False(Native.IsDevicePresent(bluetoothClassGuid));
        Assert.False(Native.IsDevicePresent(biometricClassGuid));
        Assert.True(Native.IsDevicePresent(cdromdrivClassGiud));
    }