使用 DeviceWatcher 监视 USB 驱动器并检索设备信息?

2024-02-24

I'm a WinForms开发人员和我已经知道如何使用 WMI 监视连接或断开连接的 USB,但不久前我发现了设备观察者 http://msdn.microsoft.com/en-us/library/windows.devices.enumeration.devicewatcher.aspx现代 Windows 应用程序的类,该类第一次感兴趣,因为似乎是一个非常改进和有效的替代方案,可以替换所有那些解释如何通过互联网监视驱动器的“旧”WMI 代码,但直到昨天(感谢这个帖子 https://stackoverflow.com/questions/21835653/is-possible-to-use-a-devicewatcher-in-a-winforms)我不知道如何在 WinForms 项目中使用 DeviceWatcher,但现在我正在 WinForms 项目中使用 DeviceWatcher。

问题是,也许我错了,但我认为这并不是我所期望的,只是我找不到任何有关 DeviceWatcher 的文档(只有上面的 MSDN 示例),而且我找不到方法检索必要的信息来监视驱动器事件,我尝试处理 DeviceWatcher 的所有事件,以在调试控制台中打印出参数中包含的所有数据,希望找到可以帮助我的东西......但是不,我非常坚持使用设备观察者上课,我无法想象如何继续。

当我连接或断开 USB 时,我只看到两件事,硬件 ID 和“接口启用”属性(我不知道这是否决定设备可用性),没有什么更有趣的了。

我所取得的成就:

· 检索硬件设备 ID。

我想完成什么:

· 设备连接、断开、断开时获取设备类型(以区分USB和其他类型设备)。

· 当设备连接、断开和断开连接时检索设备可用性(我的意思是设备是否可访问以读取/写入数据)。

· 设备连接、断开、断开时检索设备盘符。

· 设备连接、断开、断开时检索设备标签-描述。

代码:

Public Class DeviceWatcher_Test

    Private WithEvents dw As DeviceWatcher = DeviceInformation.CreateWatcher

    ' It's suposed that these properties should exist in the "e.properties" on the "dw_updated" event?, not in my case.
    ' Dim props As String() = {"System.ItemNameDisplay", "System.Devices.ModelName", "System.Devices.Connected"}

    Private Sub Test() Handles MyBase.Load

        dw.Start()

    End Sub

    Private Sub dw_Added(ByVal sender As DeviceWatcher, ByVal e As DeviceInformation) _
    Handles dw.Added

        Dim sb As New System.Text.StringBuilder

        With sb
            .AppendLine("dw_added")
            .AppendLine("********")
            .AppendLine(String.Format("Interface ID.: {0}", e.Id))
            .AppendLine(String.Format("Friendly Name: {0}", e.Name))
            .AppendLine(String.Format("Is Enabled?..: {0}", e.IsEnabled))
        End With

        Debug.WriteLine(sb.ToString)

    End Sub

    Private Sub dw_Removed(ByVal sender As DeviceWatcher, ByVal e As DeviceInformationUpdate) _
    Handles dw.Removed

        Dim sb As New System.Text.StringBuilder

        With sb
            .AppendLine("dw_Removed")
            .AppendLine("**********")
            .AppendLine(String.Format("Interface ID:{0}", e.Id))

            For Each item As KeyValuePair(Of String, Object) In e.Properties
                .AppendLine(String.Format("TKey:{0}, TVal:{1} (TVal Type:{2})",
                                          item.Key, item.Value.ToString, item.Value.GetType.Name))
            Next

        End With

        Debug.WriteLine(sb.ToString)

    End Sub

    Private Sub dw_Updated(ByVal sender As DeviceWatcher, ByVal e As DeviceInformationUpdate) _
    Handles dw.Updated

        Dim sb As New System.Text.StringBuilder

        With sb
            .AppendLine("dw_Updated")
            .AppendLine("**********")
            .AppendLine(String.Format("Interface ID: {0}", e.Id))

            For Each item As KeyValuePair(Of String, Object) In e.Properties

                If item.Key.EndsWith("InterfaceEnabled", StringComparison.OrdinalIgnoreCase) Then
                    Dim Result As Boolean = CBool(item.Value)
                    ' I'm not sure whether the 'Result' value really determines this:
                    .AppendLine(String.Format("The device is accessible?:{0}", CStr(Result)))

                Else
                    .AppendLine(String.Format("TKwy:{0}, TVal:{1} (TVal Type:{2})",
                                              item.Key, item.Value.ToString, item.Value.GetType.Name))

                End If

            Next

        End With

        Debug.WriteLine(sb.ToString)

    End Sub

    Private Sub dw_Stopped(ByVal sender As DeviceWatcher, ByVal e As Object) _
    Handles dw.Stopped

        Dim sb As New System.Text.StringBuilder

        With sb
            .AppendLine("dw_Stopped")
            .AppendLine("**********")
            .AppendLine(String.Format("e:{1} (e Type:{2})",
                                      e.ToString, e.GetType.Name))

        End With

        Debug.WriteLine(sb.ToString)

    End Sub

    Private Sub dw_EnumerationCompleted(ByVal sender As DeviceWatcher, ByVal e As Object) _
    Handles dw.EnumerationCompleted

        If e IsNot Nothing Then

            Dim sb As New System.Text.StringBuilder

            With sb
                .AppendLine("EnumerationCompleted")
                .AppendLine("********************")
                .AppendLine(String.Format("e:{1} (e Type:{2})",
                                          e.ToString, e.GetType.Name))

            End With

            Debug.WriteLine(sb.ToString)

        End If

    End Sub

End Class

这将监视 USB 驱动器的到达和移除,并报告驱动器号、卷标和设备序列号。为了您的方便,它提出了 2 个事件:

Public Event DeviceAdded(sender As Object, e As USBWatcherEventArgs)
Public Event DeviceRemoved(sender As Object, e As USBWatcherEventArgs)

这只监视添加/删除的新驱动器,它不会检测诸如 CD 弹出或插入或将介质插入读卡器插槽之类的情况。

Imports System.Management

Public Class USBWatcher

    ' alternate method to use one event with an extra
    ' event property to report the action
    'Public Enum WatcherActions
    '    DriveInserted = 1
    '    DriveRemoved = 2
    'End Enum

    ' USB device added/removed args
    Public Class USBWatcherEventArgs
        Inherits EventArgs

        'Public Property WatcherAction As WatcherActions
        Public Property DriveLetter As String
        Public Property VolumeName As String
        Public Property VolumeSerial As String

        Friend Sub New(drv As String, vol As String, ser As String)
            DriveLetter = drv
            VolumeName = vol
            VolumeSerial = ser
            'WatcherAction = act
        End Sub

    End Class

    Private WithEvents Watcher As ManagementEventWatcher

    Public Event DeviceAdded(sender As Object, e As USBWatcherEventArgs)
    Public Event DeviceRemoved(sender As Object, e As USBWatcherEventArgs)

    Private pnpCol As Dictionary(Of String, Management.ManagementObject)

    Public Sub New()

    End Sub

    Public Sub StartWatching()

        ' get USBs currently attached
        pnpCol = GetUSBDevices()

        Dim arriveQuery = New WqlEventQuery("Select * from Win32_DeviceChangeEvent")
        Watcher = New ManagementEventWatcher(arriveQuery)

        ' we are watching you
        Watcher.Start()

    End Sub

    Public Sub StopWatching()
        Watcher.Stop()

    End Sub

    Private Function GetUSBDevices() As Dictionary(Of String,
                        Management.ManagementObject)

        Dim col As New Dictionary(Of String, Management.ManagementObject)

        Dim moSearch As New Management.ManagementObjectSearcher("Select * from Win32_LogicalDisk")
        Dim moReturn As Management.ManagementObjectCollection = moSearch.Get


        For Each mo As Management.ManagementObject In moReturn
            'Console.WriteLine("====")
            'DebugProperties(mo)

            ' some USB external drives report as DriveType 3 (local disk), but are
            ' in fact removable.  So monitor all disk drives.
            If col.ContainsKey(mo("DeviceID").ToString) = False Then
                col.Add(mo("DeviceID").ToString, mo)
            End If

        Next

        Return col
    End Function

    Private inEvent As Boolean = False

    Private Sub arrive_EventArrived(ByVal sender As Object, 
                    ByVal e As System.Management.EventArrivedEventArgs) _
                    Handles Watcher.EventArrived

        If inEvent Then Exit Sub
        inEvent = True

        Dim col As Dictionary(Of String, Management.ManagementObject) = GetUSBDevices()

        Select Case col.Count
            Case Is > pnpCol.Count
                ' device arrived
                ProcessArrival(col)
            Case Is < pnpCol.Count
                ' device removed
                ProcessRemoval(col)
            Case Is = pnpCol.Count
                ' noise...this is a chatty rascal
        End Select

        inEvent = False

    End Sub

    Private Sub ProcessArrival(col As Dictionary(Of String,
               Management.ManagementObject))
        For Each kvp As KeyValuePair(Of String, 
                 Management.ManagementObject) In col
            If pnpCol.ContainsKey(kvp.Key) = False Then

                'Console.WriteLine("{0} {1} ", kvp.Key, kvp.Value)
                'DebugProperties(kvp.Value)

                Dim ea As New USBWatcherEventArgs(kvp.Value("DeviceID").ToString,
                                      SafeString(kvp.Value("VolumeName")),
                                      SafeString(kvp.Value("VolumeSerialNumber")))

                RaiseEvent DeviceAdded(Me, ea)

                'rebuild baseline for next event
                pnpCol = col

            End If
        Next

    End Sub

    Private Sub ProcessRemoval(col As Dictionary(Of String,
                    Management.ManagementObject))
        For Each kvp As KeyValuePair(Of String, 
                          Management.ManagementObject) In pnpCol
            If col.ContainsKey(kvp.Key) = False Then

                'Console.WriteLine("{0} {1} ", kvp.Key, kvp.Value)
                'DebugProperties(kvp.Value)

                Dim ea As New USBWatcherEventArgs(kvp.Value("DeviceID").ToString,
                                      SafeString(kvp.Value("VolumeName")),
                                      SafeString(kvp.Value("VolumeSerialNumber")))

                RaiseEvent DeviceRemoved(Me, ea)

                'rebuild baseline for next event
                pnpCol = col

            End If
        Next

    End Sub

    ' lots of things can be NOTHING depending on the manufacturer's
    ' attention to detail.  try to avoid NRE
    Private Function SafeString(obj As Object) As String

        If obj.GetType Is GetType(String) Then
            Return CType(obj, String)
        Else
            If obj IsNot Nothing Then
                Return obj.ToString
            Else
                Return "???"
            End If
        End If

    End Function

    ' debug tool to poll a management object to get the properties and values
    Private Sub DebugProperties(mo As Management.ManagementObject)

        For Each pd As PropertyData In mo.Properties
            If pd.Value IsNot Nothing Then
                Console.WriteLine("{0} {1}", pd.Name,
                                  If(pd.Value IsNot Nothing,
                                     pd.Value.ToString,
                                     "Nothing"))
            End If

        Next
    End Sub

End Class

如何实现USBWatcher

' local variable to catch events
Private WithEvents watcher As USBWatcher

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    watcher = New USBWatcher
    watcher.StartWatching()     ' or add to a button click
    ' I DONT have it starting automatically when you create the watcher

End Sub

设备观察程序在不同的线程上运行,因此如果您想向控件发布通知,则必须使用委托:

Delegate Sub AddListItem(text As String)
Private myDelegate As AddListItem = New AddListItem(AddressOf AddNewListItem)

Private Sub AddNewListItem(text As String)
    myListBox.Items.Add(text)
End Sub

然后从设备添加事件中,例如:

Private Sub watcher_DeviceAdded(sender As Object, 
            e As USBWatcher.USBWatcherEventArgs) Handles watcher.DeviceAdded

    Console.Beep()

    Dim msg As String = String.Format("Drive {0} ({1})   {2}", 
                                       e.DriveLetter,
                                       e.VolumeName, "Inserted")
    If myListBox.InvokeRequired Then
        myListBox.Invoke(myDelegate, New Object() {msg})
    Else
        myListBox.Items.Add(msg)
    End If

End Sub

DeviceRemoved 与消息文本中的第三个参数“Removed”不同。

USB观察者还有一个StopWatching暂时关闭观察者的方法,以及StartWatching启动并重新启动它。您的应用程序应该调用StopWatching当应用程序结束时以防止 COM 错误;只需添加watcher.StopWatching在表单关闭事件中。

这可以满足您的需求 - 在插入可移动媒体时引发事件并返回有关它们的信息 - 只是不完全一样how你想要它。它使用久经考验的 WMI,而不是 Win8 方法,而 Win8 方法在 MSDN 上只有稀疏的文档,并且只能在 Win8 上运行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 DeviceWatcher 监视 USB 驱动器并检索设备信息? 的相关文章

  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • 哪些属性有助于运行时 .Net 性能?

    我正在寻找可用于通过向加载器 JIT 编译器或 ngen 提供提示来确保 Net 应用程序获得最佳运行时性能的属性 例如我们有可调试属性 http msdn microsoft com en us library k2wxda47 aspx
  • 我可以将 SimpleInjectors 诊断结果写入日志文件吗?

    在调用中使用简单注入器container Verify 在我的配置结束时 并在调试器中获取诊断信息 如中所述文档 http simpleinjector codeplex com wikipage title Diagnostics 我想将
  • 如何检查 FTP 目录是否存在

    寻找通过 FTP 检查给定目录的最佳方法 目前我有以下代码 private bool FtpDirectoryExists string directory string username string password try var r
  • .Net 中是否有与 HTML 等效的 XmlReader?

    我用过Html敏捷包 http html agility pack net z codeplex过去在 Net 中解析 HTML 但我不喜欢它只使用 DOM 模型 在大型文档和 或具有大量嵌套的文档上 可能会遇到堆栈溢出或内存不足异常 另外
  • 为什么在为 Silverlight 5 应用程序添加编码 UI 支持时 System.Core 无法加载?

    我遇到以下问题 尝试添加对为 Silverlight 5 应用程序创建编码 UI 测试的支持 MSDN 1 第一步是在 Silverlight 5 项目中引用程序集 Microsoft VisualStudio TestTools UITe
  • 从 Form2 访问 Form1 控件

    有两个表单 Form1和Form2 Form1有一个按钮 btnNew 单击时打开Form2 并且被禁用 我需要再次启用该按钮 只有当Form2关闭时 用户也需要同时使用Form1 这段代码不再启用该按钮 我哪里失踪了 在表格1中 priv
  • 实体框架代码首先保存后不延迟加载

    我的数据库中有一个查找表和一个数据表 我将使用性别和人物作为例子 假设性别表如下所示 Id Code 1 Male 2 Female 人员表如下所示 Id Name GenderId 1 Bob 1 2 Jane 2 我首先在 EF 代码中
  • 如何在 sql server 中加密数据并在 .net 应用程序中解密

    我想加密 sql server 中的一些密码并让 c 应用程序解密它们 显然 我可以创建一个 SP 来解密所需的密码并将其传递给 c 应用程序 但这意味着通过网络发送明文密码 因此 我希望能够在 sql server 中加密我的密码 使用密
  • 从 .net 应用程序登录 OpenID 站点

    我一直在考虑编写一个小工具来登录 SO 并定期使用一些主题 当前信息更新我的个人资料信息 例如我最新的博客文章或我需要帮助的问题等 为了让它工作 我需要以某种方式从控制台应用程序登录到SO 是否有一个 Net 库可以简化使用原始 http
  • 如何使用AutoMapper按照类中定义的顺序映射对象?

    给定这两个对象 我使用非常不同的对象来更好地阐明 public class Car public string Brand get set public int Speed get set public class Apple public
  • Lazy 实现和 .NET 泛型

    我正在寻找进行延迟初始化的方法并发现Lazy
  • MySQL - 多个结果集

    我正在使用 NET Connector 连接到 MySQL 在我的应用程序中 很少有线程使用相同的连接 因此如果 MySQLDataReader 尚未关闭并且某个线程正在尝试执行查询 则会出现该错误 已经有一个打开的 DataReader
  • 将 Windows 窗体应用程序转换为 Asp.net

    我问的是 您之前使用的将 C Windows 窗体应用程序转换为 ASP NET 的最佳工具是什么 我已经关于这个主题 发现了很多工具 但我希望有人根据他的使用情况推荐最好的工具 我真的不建议使用工具来进行转换 Web 应用程序和 WinF
  • 什么可以解释托管堆上超过 5,000,000 个 System.WeakReference 实例?

    我一直在针对生产 ASP NET Web 应用程序运行负载测试 并且看到在堆上创建了大量 System WeakReference 在大约 15 分钟内 负载管理堆内存已飙升至大约 3GB 并且我有大约 5 000 000 个对 Syste
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ

随机推荐