Как сделать элемент управления WinForm Visible = True при обнаружении USB-устройства в VB.NET - PullRequest
0 голосов
/ 03 июля 2018

Работа с существующим кодом в VB.net. Работает хорошо, пока я не добавлю дополнительные функции в код для выполнения других задач. Например, приведенный ниже код генерирует исключения в окне «Немедленно» при попытке сделать кнопку видимой, когда она обнаруживает вставленный флэш-накопитель USB. Я предполагаю, что это происходит, потому что кнопка еще не полностью создана? В любом случае, ищу направление, как я могу это исправить. Все, что я хочу сделать, это сделать кнопку видимой, когда USB-накопитель вставлен, и НЕ видимой, когда USB-накопитель извлечен. Заранее спасибо!

КОД:

Imports System.Management ' Also had to add System.Management as a reference
Imports System
Imports System.ComponentModel

Public Class Form1

    Private WithEvents m_MediaConnectWatcher As ManagementEventWatcher
    Public USBDriveName As String
    Public USBDriveLetter As String

    Public Sub StartDetection()
        ' __InstanceOperationEvent will trap both Creation and Deletion of class instances
        Dim query2 As New WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 1 " _
  & "WHERE TargetInstance ISA 'Win32_DiskDrive'")

        m_MediaConnectWatcher = New ManagementEventWatcher With {
            .Query = query2
        }
        m_MediaConnectWatcher.Start()
    End Sub


    Private Sub Arrived(ByVal sender As Object, ByVal e As System.Management.EventArrivedEventArgs) Handles m_MediaConnectWatcher.EventArrived

        Dim mbo, obj As ManagementBaseObject

        ' the first thing we have to do is figure out if this is a creation or deletion event
        mbo = CType(e.NewEvent, ManagementBaseObject)
        ' next we need a copy of the instance that was either created or deleted
        obj = CType(mbo("TargetInstance"), ManagementBaseObject)

        Select Case mbo.ClassPath.ClassName
            Case "__InstanceCreationEvent"
                If obj("InterfaceType") = "USB" Then
                    MsgBox("Technician maintenance key has been plugged in")
                    Button1.Visible = True
                Else
                    MsgBox(obj("InterfaceType"))
                End If
            Case "__InstanceDeletionEvent"
                If obj("InterfaceType") = "USB" Then
                    MsgBox("Technician maintenance key has been unplugged.")
                    Button1.Visible = False
                    If obj("Caption") = USBDriveName Then
                        USBDriveLetter = ""
                        USBDriveName = ""
                    End If
                Else
                    MsgBox(obj("InterfaceType"))
                End If
            Case Else
                MsgBox("nope: " & obj("Caption"))
        End Select
    End Sub

    Private Function GetDriveLetterFromDisk(ByVal Name As String) As String
        Dim oq_part, oq_disk As ObjectQuery
        Dim mos_part, mos_disk As ManagementObjectSearcher
        Dim obj_part, obj_disk As ManagementObject
        Dim ans As String = ""

        ' WMI queries use the "\" as an escape charcter
        Name = Replace(Name, "\", "\\")

        ' First we map the Win32_DiskDrive instance with the association called
        ' Win32_DiskDriveToDiskPartition. Then we map the Win23_DiskPartion
        ' instance with the assocation called Win32_LogicalDiskToPartition

        oq_part = New ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & Name & """} WHERE AssocClass = Win32_DiskDriveToDiskPartition")
        mos_part = New ManagementObjectSearcher(oq_part)
        For Each obj_part In mos_part.Get()

            oq_disk = New ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & obj_part("DeviceID") & """} WHERE AssocClass = Win32_LogicalDiskToPartition")
            mos_disk = New ManagementObjectSearcher(oq_disk)
            For Each obj_disk In mos_disk.Get()
                ans &= obj_disk("Name") & ","
            Next
        Next

        Return ans.Trim(","c)
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        StartDetection()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        m_MediaConnectWatcher.Stop()
        Application.Exit()
    End Sub

    Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        m_MediaConnectWatcher.Stop()
        Application.Exit()
    End Sub
End Class

1 Ответ

0 голосов

Когда поток, отличный от того, который создал элемент управления (в вашем случае Button1), пытается вызвать этот элемент управления ( Button1.Visible = True или Button1.Visible = False ), отладчик вызывает исключение InvalidOperationException с сообщением Имя элемента управления, доступ к которому получен из потока, отличного от потока, в котором он был создан. Возможно, это сообщение, которое вы видите. Одним из способов доступа к элементам управления из разных потоков является использование Invoke () :

Private Sub ShowButton()
    'InvokeRequired compares the thread ID of the  
    'calling thread to the thread ID of the creating thread.  
    'If these threads are different, it returns true.
    'If the calling thread is different from the thread that  
    'created the Button1 control, this method calls itself asynchronously using the  
    'Invoke method
    If Me.InvokeRequired Then
        Me.Invoke(Sub() ShowButton())
        Return
    End If

    Button1.Visible = True
End Sub

Private Sub HideButton()
    If Me.InvokeRequired Then
        Me.Invoke(Sub() HideButton())
        Return
    End If

    Button1.Visible = False
End Sub

и в вашем коде замените

Button1.Visible = True

с

ShowButton()

и

Button1.Visible = False

с

HideButton()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...