问题
I'm trying to make a screen locker software, that unlocks only when the correct flash drive plugged in and locks when it's unplugged. So that I have searched and found some codes that detects flash drive. It works properly when there is only one flash drive but if there are more than one flash drive and I unplugged the one without pass, my software still locks the screen. Can anyone help with it?
here is my codes
Imports System.Runtime.InteropServices
Imports System.IO
Public Class Form1
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
e.Cancel = True
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
Me.TopMost = True
End Sub
Private Const WM_DEVICECHANGE As Integer = &H219
Private Const DBT_DEVICEARRIVAL As Integer = &H8000
Private Const DBT_DEVTYP_VOLUME As Integer = &H2
Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
Public Structure DEV_BROADCAST_HDR
Public dbch_size As Int32
Public dbch_devicetype As Int32
Public dbch_reserved As Int32
End Structure
Private Structure DEV_BROADCAST_VOLUME
Public dbcv_size As Int32
Public dbcv_devicetype As Int32
Public dbcv_reserved As Int32
Public dbcv_unitmask As Int32
Public dbcv_flags As Int16
End Structure
Private Function GetDriveLetterFromMask(ByRef Unit As Int32) As Char
For i As Integer = 0 To 25
If Unit = (2 ^ i) Then
Return Chr(Asc("A") + i)
End If
Next
End Function
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_DEVICECHANGE Then
If m.WParam.ToInt32 = DBT_DEVICEARRIVAL Then
If CInt(m.WParam) = DBT_DEVICEARRIVAL Then
Dim DeviceInfo As DEV_BROADCAST_HDR
DeviceInfo = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_HDR)), DEV_BROADCAST_HDR)
If DeviceInfo.dbch_devicetype = DBT_DEVTYP_VOLUME Then
Dim Volume As DEV_BROADCAST_VOLUME
Volume = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_VOLUME)), DEV_BROADCAST_VOLUME)
Dim DriveLetter As String = (GetDriveLetterFromMask(Volume.dbcv_unitmask) & ":\")
If IO.File.Exists(IO.Path.Combine(DriveLetter, "password.info")) Then
Dim fso As Scripting.FileSystemObject
Dim oDrive As Scripting.Drive
fso = CreateObject("Scripting.FileSystemObject")
oDrive = fso.GetDrive(DriveLetter)
Dim passline As String() = File.ReadAllLines(DriveLetter & "password.info")
If passline(3) = "1120" & oDrive.SerialNumber Then
MessageBox.Show("Welcome!")
Me.TopMost = False
Me.WindowState = FormWindowState.Minimized
Else
MsgBox("This is not your password.")
End If
Else
MessageBox.Show("Password couldn't be found!")
End If
End If
End If
End If
If m.WParam.ToInt32 = DBT_DEVICEREMOVECOMPLETE Then
Me.WindowState = FormWindowState.Maximized
Me.TopMost = True
MsgBox("Device is removed!")
End If
Else
End If
MyBase.WndProc(m)
End Sub
End Class
回答1:
Since you can't get the device ID when the drive is removed, you can not tell which device was removed, all you know is SOMETHING was removed.
At that point you really need to scan and see if the expected drive is still connected.
You need to store the DriveLetter of the right USB Drive in the class when it is detected, then check it still exists when a drive is removed..
Something like
Dim Key_Is_Gone = True
For Each drv As DriveInfo In My.Computer.FileSystem.Drives
If drv.Name = DriveLetter Then
Key_Is_Gone = False
Exit For
End If
Next
If Key_Is_Gone Then
'Do what you have to do
End If
Though if the drive letter does exist, you may want to check some other property of the drive to verify it is really the same key. Otherwise, some bright spark may reassign the drive letters on you.
Perhaps
drv.RootDirectory.CreationTime
Read and store that on detecting the Key, and use that stored value to test.
Dim Key_Is_Gone = True
For Each drv As DriveInfo In My.Computer.FileSystem.Drives
If drv.Name = DriveLetter andalso drv.RootDirectory.CreationTime = DetectedKeyDate Then
Key_Is_Gone = False
Exit For
End If
Next
If Key_Is_Gone Then
'Do what you have to do
End If
ALSO: Don't use FSO, use the native VB.NET
My.Computer.FileSystem
objects instead.
回答2:
You can get device type if it's the only removable device and then do whatever you want
Dim folder = New FolderBrowserDialog()
Dim drives = System.IO.DriveInfo.GetDrives()
Dim usbDrive = drives.FirstOrDefault(Function(m) m.DriveType = System.IO.DriveType.Removable)
For i As Integer = 0 To drives.Count - 1
If drives(i).DriveType = System.IO.DriveType.Removable Then
'Codes will not run if there were no removable device
folder.SelectedPath = usbDrive.RootDirectory.FullName
MessageBox.Show(folder.SelectedPath)
End If
Next i
Codes are in Visual Basic language
来源:https://stackoverflow.com/questions/42259734/how-to-detect-first-plug-usb-flash-memory-on-vb-net