【问题标题】:How to detect nonpresent devices using C#如何使用 C# 检测不存在的设备
【发布时间】:2014-12-17 03:07:53
【问题描述】:

我的程序(完全用 C# 编写)有一个用例,程序需要检测计算机中是否安装了特定的 USB 设备。在连接了 USB 设备的情况下,WMI 将解决这个问题。

但是,如果设备未连接(不存在的设备),那么 WMI 将无法提供帮助。我知道 setupdi 可能会帮助解决这个问题,但是我对 C++ 并不完全熟悉,并且由于符合现有代码部分,因此添加编组函数的额外工作非常重要。

因此我的问题是是否有等效的 c# 方法来检测系统中不存在的设备?我也试过注册表搜索的方法,但是驱动是HKLM\System\CurrentControlSet\services\WinUSB下的通用USB驱动,并没有额外的信息可以用来识别USB驱动对应具体的设备我们感兴趣。

另一个可能的识别信息是设备管理器中驱动程序选项卡中的“驱动程序提供程序”信息。 usb 设备有相当具体的驱动程序提供者信息,可用于识别设备。但是我不知道现有的 API 来检索这些信息。

非常感谢您的帮助并期待任何可能的解决方案

【问题讨论】:

    标签: c# device-manager


    【解决方案1】:

    不知道这是否有帮助。这是我大约 7 年前写的一些 sn-ps 代码,从那以后就没有使用过 - 该项目被放弃了。不幸的是,整个 USB 接口大约有 700 行 C# - 太多了,无法在此处发布。

       /// <summary>
       /// This class represents a USB HID (Human Interface Device) device.
       /// </summary>
       public class UsbHidDevice : IDisposable
       {
    
          // The Windows GUID for HID USB devices
          private Guid _deviceClass;
    
          // The full "path name" of the device (set when found)
          private string _devicePath;
    
    
          #region Constructor
    
          public UsbHidDevice()
          {
             // Initialize the Windows GUID for HID devices
             Win32API.HidD_GetHidGuid(out _deviceClass);
          }
    
          #endregion Constructor
    
    
          /// <summary>
          /// Function to search the USB devices to see if the desired one is online.
          /// </summary>
          /// <param name="vendorId">vendor ID, or zero if not significant</param>
          /// <param name="productId">product ID</param>
          public bool FindDevice(int vendorId, int productId)
          {
             string strSearch;
    
             // Build the path search string
             if (vendorId == 0)
                strSearch = string.Format("pid_{0:x4}", productId);
             else
                strSearch = string.Format("vid_{0:x4}&pid_{1:x4}", vendorId, productId);
    
             // Prepare to search the USB device table in Windows
             // This gets a list of all HID devices currently connected to the computer (InfoSet)
             IntPtr hInfoSet = Win32API.SetupDiGetClassDevs(ref _deviceClass, null, IntPtr.Zero, Win32API.DIGCF_DEVICEINTERFACE | Win32API.DIGCF_PRESENT);
    
             try
             {
                // Build up a device interface data block
                Win32API.DeviceInterfaceData oInterface = new Win32API.DeviceInterfaceData();
                oInterface.Size = Marshal.SizeOf(oInterface);
    
                // Now iterate through the InfoSet memory block assigned within Windows in the 
                //  call to SetupDiGetClassDevs to get device details for each device connected
                int nIndex = 0;
    
                // This gets the device interface information for a device at index 'nIndex' in the memory block
                while (Win32API.SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref _deviceClass, (uint)nIndex, ref oInterface))
                {
                   // Get the device path (see helper method 'GetDevicePath')
                   string strDevicePath = GetDevicePath(hInfoSet, ref oInterface);
    
                   // Do a string search, if we find the VID/PID string then we found our device
                   if (!string.IsNullOrEmpty(strDevicePath) && strDevicePath.IndexOf(strSearch) >= 0)
                   {
                      _devicePath = strDevicePath;
                      return true;
                   }
    
                   // If we get here, we didn't find our device. So move on to the next one.
                   log.Debug("FindDevice() - Incorrect device found, keep searching." + strDevicePath);
                   nIndex++;
                }
             }
    
             catch (Exception e)
             {
                log.Error("FindDevice() - Exception:", e);
             }
    
             finally
             {
                // Before we go, we have to free up the InfoSet memory reserved by SetupDiGetClassDevs
                Win32API.SetupDiDestroyDeviceInfoList(hInfoSet);
             }
    
             // Device not found
             return false;
          }
    
    ... other methods not included here
       }
    
    
       /// <summary>
       /// Definition of some Windows API stuff.
       /// 
       /// This is copied from "A USB HID Component for C#" (also called "Sniffer"), By "wimar"
       ///  http://www.codeproject.com/KB/cs/USB_HID.aspx
       /// </summary>
       internal class Win32API
       {
          // Used in SetupDiClassDevs to get devices present in the system
          public const int DIGCF_PRESENT = 0x02;
    
          // Used in SetupDiClassDevs to get device interface details
          public const int DIGCF_DEVICEINTERFACE = 0x10;
    
    
          /// <summary>
          /// Provides details about a single USB device
          /// 
          /// The field "Reserved" has been changed from int to UIntPtr based on information on web page
          /// http://www.codeproject.com/KB/cs/USB_HID.aspx, see message "Does not work on 64 bit Vista?".
          /// </summary>
          [StructLayout(LayoutKind.Sequential, Pack = 1)]
          public struct DeviceInterfaceData
          {
             public int Size;
             public Guid InterfaceClassGuid;
             public int Flags;
             public UIntPtr Reserved;
          }
    
    
          /// <summary>
          /// Gets the GUID that Windows uses to represent HID class devices
          /// </summary>
          /// <param name="gHid">An out parameter to take the Guid</param>
          [DllImport("hid.dll", SetLastError = true)]
          public static extern void HidD_GetHidGuid(out Guid gHid);
          /// <summary>
          /// Allocates an InfoSet memory block within Windows that contains details of devices.
          /// </summary>
          /// <param name="gClass">Class guid (e.g. HID guid)</param>
          /// <param name="strEnumerator">Not used</param>
          /// <param name="hParent">Not used</param>
          /// <param name="nFlags">Type of device details required (DIGCF_ constants)</param>
          /// <returns>A reference to the InfoSet</returns>
          [DllImport("setupapi.dll", SetLastError = true)]
          public static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, [MarshalAs(UnmanagedType.LPStr)] string strEnumerator, IntPtr hParent, uint nFlags);
    
    
          /// <summary>
          /// Gets the DeviceInterfaceData for a device from an InfoSet.
          /// </summary>
          /// <param name="lpDeviceInfoSet">InfoSet to access</param>
          /// <param name="nDeviceInfoData">Not used</param>
          /// <param name="gClass">Device class guid</param>
          /// <param name="nIndex">Index into InfoSet for device</param>
          /// <param name="oInterfaceData">DeviceInterfaceData to fill with data</param>
          /// <returns>True if successful, false if not (e.g. when index is passed end of InfoSet)</returns>
          [DllImport("setupapi.dll", SetLastError = true)]
          public static extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet, uint nDeviceInfoData, ref Guid gClass, uint nIndex, ref DeviceInterfaceData oInterfaceData);
    
    
          /// <summary>
          /// Frees InfoSet allocated in call to above.
          /// </summary>
          /// <param name="lpInfoSet">Reference to InfoSet</param>
          /// <returns>true if successful</returns>
          [DllImport("setupapi.dll", SetLastError = true)]
          public static extern int SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);
    
    ... other stuff missing
       }
    

    正如代码中的注释中提到的,这是基于此:http://www.codeproject.com/Articles/18099/A-USB-HID-Component-for-C

    我可能遗漏了一些需要的东西 - 请告诉我。

    【讨论】:

    • 感谢您的反馈,我已经使用 Win32API 实现了类似的东西。谢谢!
    【解决方案2】:
            string ComputerName = "localhost";
            ManagementScope Scope;
            Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
    
            Scope.Connect();
    
            string query = "SELECT * FROM Win32_PnPEntity Where ClassGuid = NULL";
    
            ObjectQuery Query = new ObjectQuery(query);
    
            ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
    
            foreach (ManagementObject WmiObject in Searcher.Get())
            {
                textBox1.Text += WmiObject["Name"] + "\r\n";
            }
    

    【讨论】:

    • 不要只在答案中发布代码。试着向提问者解释一下
    • 特别是当 OP 声明“那么 WMI 将无法提供帮助”时。既然您的代码只是一个 WMI 查询,请解释为什么它会违背 OP 的期望。
    • 感谢您提供可能有助于解决问题的代码,但一般来说,如果答案包含对代码的用途以及解决问题的原因的解释,则会更有帮助。跨度>
    猜你喜欢
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多