如何检测U盘并定时提醒备份?
问题:1、自动运行,但想直接最小化在托盘显示,或者在后台隐藏之类的。
2、有U盘插入后自动检测,然后提醒是否要备份,然后可以自己设定间隔多长时间提示备份,或者在电脑里留个记录文件,每隔1个月提示备份一次该U盘。
3、运行时占用内存6m,能否精简,启动载入速度也不够理想,如何优化?
2012-10-12 15:58

2012-10-12 19:44
程序代码:
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3510
ClientLeft = 60
ClientTop = 450
ClientWidth = 6015
LinkTopic = "Form1"
ScaleHeight = 3510
ScaleWidth = 6015
StartUpPosition = 3 '系统预设值
Begin VB.ListBox List1
Height = 3300
Left = 120
TabIndex = 0
Top = 120
Width = 5775
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Sub Form_Load()
'子类化窗体的消息处理函数
HookForm Me
End Sub
Private Sub Form_Unload(Cancel As Integer)
'程序退出时恢复原窗体处理函数
UnHookForm Me
End Sub
'效果图:
'备注:本示例程序不仅仅能检测U盘的插入,对CDROM、网络映射盘等设备也会作出同样的反应,如果需要只检测U盘,则需要在If info.lDevicetype =DBT_DEVTYP_VOLUME
'处再对iFlag结构成员作检测,其数值为0时表示设备为U盘。另外根据微软的解释,软盘的插拔是不会有引发该消息的,原因是只有支持软弹出技术的设备才会引发该消息。
'(原文:Messages for media arrival and removal are sent only for media in devices that support a soft-eject mechanism. )
'本演示程序在WINDOWS98、XP系统下调试通过。
程序代码:
'VB: 如何检测到U盘的插拔 (源代码)
'2007年06月02日 星期六 23:22
'听说现在网络上流传着一些能实时检测到U盘插拔消息并能在其插入后伺机拷贝其中文档资料的恶意程序,而日前在CSDN论坛也看到有网友询问这类程序的实现原理,为此我想通过一个简单的VB程序演示一下核心操作过程并藉机把实现原理作一个简洁的说明。
'事实上当U盘(实际上不局限于U盘,所有能在系统中获得逻辑卷标的设备都适用)插入视窗系统的机器后操作系统将发送一个WM_DEVICECHANGE的广播消息,因此只要在相应的消息处理过程中拦截该信息并加以处理就能实时检测到U盘的插拔,之后即可进行预设的有关处理动作了。
'熟悉WINDOWS消息处理过程的人都知道,操作系统发送有关消息时还会附带上两个重要的参数:wParam、lParam,因此WM_DEVICECHANGE也不例外,当该消息发生时,wParam里的内容是指示设备变化的具体事件类别,在我们的演示程序里只需要关心DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE这两个事件,前者表示新设备已经插入机器并能正常使用了,后者表示设备已经被物理移除了;lParam的内容实际上是一个地址,指向一个结构体,该结构的具体细节由插入系统的设备类型决定,这里有个需要注意的地方,即不论设备类型是什么,该结构的前面三个LONG型成员是固定的,因此我们可以先取得这三个成员的内容,再根据第二个成员的数值来确定新设备类型,然后再获取全部成员的内容。
' 以下是这个VB演示程序的代码,效果就是检测到设备插入后即把该设备根目录下的全部文件名显示在LISTBOX里面。
'‘子类化窗体消息处理函数时需要使用的API,很常见,不作过多说明。
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Const GWL_WNDPROC = -4
Private Const WM_DEVICECHANGE As Long = &H219
Private Const DBT_DEVICEARRIVAL As Long = &H8000&
Private Const DBT_DEVICEREMOVECOMPLETE As Long = &H8004&
'设备类型:逻辑卷标
Private Const DBT_DEVTYP_VOLUME As Long = &H2
'与WM_DEVICECHANGE消息相关联的结构体头部信息
Private Type DEV_BROADCAST_HDR
lSize As Long
lDevicetype As Long '设备类型
lReserved As Long
End Type
'设备为逻辑卷时对应的结构体信息
Private Type DEV_BROADCAST_VOLUME
lSize As Long
lDevicetype As Long
lReserved As Long
lUnitMask As Long '和逻辑卷标对应的掩码
iFlag As Integer
End Type
Private info As DEV_BROADCAST_HDR
Private info_volume As DEV_BROADCAST_VOLUME
Private PrevProc As Long '‘原来的窗体消息处理函数地址
Public Sub HookForm(F As Form)
PrevProc = SetWindowLong(F.hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Public Sub UnHookForm(F As Form)
SetWindowLong F.hwnd, GWL_WNDPROC, PrevProc
End Sub
Private Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
'插入USB DISK 则接收到此消息
Case WM_DEVICECHANGE
If wParam = DBT_DEVICEARRIVAL Then
'若插入USBDISK或者映射网络盘等则
'info.lDevicetype =2
'即DBT_DEVTYP_VOLUME
'利用参数lParam获取结构体头部信息
CopyMemory info, ByVal lParam, Len(info)
If info.lDevicetype = DBT_DEVTYP_VOLUME Then
CopyMemory info_volume, ByVal lParam, Len(info_volume)
'检测到有逻辑卷添加到系统中,则显示该设备根目录下全部文件名
ListFiles Chr(GetDriveName(info_volume.lUnitMask)) & ":\", Form1.List1
End If
End If
If wParam = DBT_DEVICEREMOVECOMPLETE Then
'若移走USBDISK或者映射网络盘等则
'info.lDevicetype =2
'即DBT_DEVTYP_VOLUME
'利用参数lParam获取结构体头部信息
CopyMemory info, ByVal lParam, Len(info)
If info.lDevicetype = DBT_DEVTYP_VOLUME Then
CopyMemory info_volume, ByVal lParam, Len(info_volume)
'清除LIST中的内容
Form1.List1.Clear
End If
End If
End Select
' 调用原来的窗体消息处理函数
WindowProc = CallWindowProc(PrevProc, hwnd, uMsg, wParam, lParam)
End Function
'根据输入的32位LONG型数据(只有一位为1)返回对应的卷标的ASCII数值
'规则是1:A、2:B、4:C等等
Private Function GetDriveName(ByVal lUnitMask As Long) As Byte
Dim i As Long
i = 0
While lUnitMask Mod 2 <> 1
lUnitMask = lUnitMask \ 2
i = i + 1
Wend
GetDriveName = Asc("A") + i
End Function
'显示插入逻辑卷根目录的文件名列表,需要在工程里引用Microsoft Scripting Runtime库。
Private Function ListFiles(strPath As String, ByRef list As ListBox)
Dim fso As New Scripting.FileSystemObject
Dim objFolder As Folder
Dim objFile As File
Set objFolder = fso.GetFolder(strPath)
For Each objFile In objFolder.Files
list.AddItem objFile.Name
Next
End Function

2012-10-12 19:53
程序代码:
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3090
ClientLeft = 60
ClientTop = 450
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3090
ScaleWidth = 4680
StartUpPosition = 3 '系統預設值
Begin VB.Timer Timer1
Left = 3840
Top = 240
End
Begin Command2
Caption = "Command2"
Height = 495
Left = 2160
TabIndex = 1
Top = 240
Width = 1335
End
Begin Command1
Caption = "Command1"
Height = 495
Left = 360
TabIndex = 0
Top = 240
Width = 1335
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'用VB實現卸載U盤
'一般在拔U盤之前,都要先「安全刪除硬件」的,用VB能實現這個功能嗎?
'解答之一:
'Shell "RUNDLL32.EXE shell32.dll,Control_RunDLL hotplug.dll"
'這句代碼可以彈出安全刪除硬件的窗口,可是我想要的不是這樣的效果,我需要直接把U盤安全刪除掉,不用彈出窗口。也就是自動安全刪除U盤。這樣有辦法嗎?
'解答2:
'代碼開始:
Option Explicit
'QQ:121877114 丹心軟件設計
'E-MAIL:CNSTARWORK@
'2007.6.1
Dim boTimeOut As Boolean
Private Const DRIVE_CDROM As Long = 5
Private Const DRIVE_REMOVABLE As Long = 2
Private Const GENERIC_READ As Long = &H80000000
Private Const GENERIC_WRITE As Long = &H40000000
Private Const OPEN_EXISTING As Long = 3
Private Const FILE_DEVICE_FILE_SYSTEM As Long = 9
Private Const FILE_DEVICE_MASS_STORAGE As Long = &H2D&
Private Const METHOD_BUFFERED As Long = 0
Private Const FILE_ANY_ACCESS As Long = 0
Private Const FILE_READ_ACCESS As Long = 1
Private Const LOCK_VOLUME As Long = 6
Private Const DISMOUNT_VOLUME As Long = 8
Private Const EJECT_MEDIA As Long = &H202
Private Const MEDIA_REMOVAL As Long = &H201
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const LOCK_TIMEOUT As Long = 1000
Private Const LOCK_RETRIES As Long = 20
Private Declare Function GetDriveType Lib "kernel32.dll" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByRef lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function DeviceIoControl Lib "kernel32.dll" (ByVal hDevice As Long, ByRef dwIoControlCode As Long, ByRef lpInBuffer As Any, ByVal nInBufferSize As Long, ByRef lpOutBuffer As Any, ByVal nOutBufferSize As Long, ByRef lpBytesReturned As Long, ByRef lpOverlapped As Long) As Long
Private Function CTL_CODE(lngDevFileSys As Long, lngFunction As Long, lngMethod As Long, lngAccess As Long) As Long
CTL_CODE = (lngDevFileSys * (2 ^ 16)) Or (lngAccess * (2 ^ 14)) Or (lngFunction * (2 ^ 2)) Or lngMethod
End Function
Private Function OpenVolume(strLetter As String, lngVolHandle As Long) As Boolean
Dim lngDriveType As Long
Dim lngAccessFlags As Long
Dim strVolume As String
lngDriveType = GetDriveType(strLetter)
Select Case lngDriveType
Case DRIVE_REMOVABLE
lngAccessFlags = GENERIC_READ Or GENERIC_WRITE
Case DRIVE_CDROM
lngAccessFlags = GENERIC_READ
Case Else
OpenVolume = False
Exit Function
End Select
strVolume = "\\.\" & strLetter
lngVolHandle = CreateFile(strVolume, lngAccessFlags, 0, ByVal CLng(0), OPEN_EXISTING, ByVal CLng(0), ByVal CLng(0))
If lngVolHandle = INVALID_HANDLE_VALUE Then
OpenVolume = False
Exit Function
End If
OpenVolume = True
End Function
Private Function CloseVolume(lngVolHandle As Long) As Boolean
Dim lngReturn As Long
lngReturn = CloseHandle(lngVolHandle)
If lngReturn = 0 Then
CloseVolume = False
Else
CloseVolume = True
End If
End Function
Private Function LockVolume(ByRef lngVolHandle As Long) As Boolean
Dim lngBytesReturned As Long
Dim intCount As Integer
Dim intI As Integer
Dim boLocked As Boolean
Dim lngFunction As Long
lngFunction = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, LOCK_VOLUME, METHOD_BUFFERED, FILE_ANY_ACCESS)
intCount = LOCK_TIMEOUT / LOCK_RETRIES
boLocked = False
For intI = 0 To LOCK_RETRIES
boTimeOut = False
Timer1.Interval = intCount
Timer1.Enabled = True
Do Until boTimeOut = True Or boLocked = True
boLocked = DeviceIoControl(lngVolHandle, ByVal lngFunction, CLng(0), 0, CLng(0), 0, lngBytesReturned, ByVal CLng(0))
DoEvents
Loop
If boLocked = True Then
LockVolume = True
Timer1.Enabled = False
Exit Function
End If
Next intI
LockVolume = False
End Function
Private Function DismountVolume(lngVolHandle As Long) As Boolean
Dim lngBytesReturned As Long
Dim lngFunction As Long
lngFunction = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, DISMOUNT_VOLUME, METHOD_BUFFERED, FILE_ANY_ACCESS)
DismountVolume = DeviceIoControl(lngVolHandle, ByVal lngFunction, 0, 0, 0, 0, lngBytesReturned, ByVal 0)
End Function
Private Function PreventRemovalofVolume(lngVolHandle As Long) As Boolean
Dim boPreventRemoval As Boolean
Dim lngBytesReturned As Long
Dim lngFunction As Long
boPreventRemoval = False
lngFunction = CTL_CODE(FILE_DEVICE_MASS_STORAGE, MEDIA_REMOVAL, METHOD_BUFFERED, FILE_READ_ACCESS)
PreventRemovalofVolume = DeviceIoControl(lngVolHandle, ByVal lngFunction, boPreventRemoval, Len(boPreventRemoval), 0, 0, lngBytesReturned, ByVal 0)
End Function
Private Function AutoEjectVolume(lngVolHandle As Long) As Boolean
Dim lngFunction As Long
Dim lngBytesReturned As Long
lngFunction = CTL_CODE(FILE_DEVICE_MASS_STORAGE, EJECT_MEDIA, METHOD_BUFFERED, FILE_READ_ACCESS)
AutoEjectVolume = DeviceIoControl(lngVolHandle, ByVal lngFunction, 0, 0, 0, 0, lngBytesReturned, ByVal 0)
End Function
Private Sub Eject(strVol As String)
Dim lngVolHand As Long
Dim boResult As Boolean
Dim boSafe As Boolean
strVol = strVol & ":"
'
' Open and get a Handle for the Volume
'
boResult = OpenVolume(strVol, lngVolHand)
If boResult = False Then
MsgBox "Error Opening Volume " & Err.LastDllError
Exit Sub
End If
'
' Lock the Volume
'
boResult = LockVolume(lngVolHand)
If boResult = False Then
MsgBox "Error Dismounting Volume " & Err.LastDllError
CloseVolume (lngVolHand)
Exit Sub
End If
'
'Dismount the Volume
'
boResult = DismountVolume(lngVolHand)
If boResult = False Then
MsgBox "Error Dismounting Volume " & Err.LastDllError
CloseVolume (lngVolHand)
Exit Sub
End If
'
' Set to allow the Volume to be Removed
'
boResult = PreventRemovalofVolume(lngVolHand)
If boResult = False Then
MsgBox "Error Allowing Removal of Volume " & Err.LastDllError
CloseVolume (lngVolHand)
Exit Sub
End If
boSafe = True
'
' Eject the Volume
'
boResult = AutoEjectVolume(lngVolHand)
If boSafe = True Then
MsgBox "Media may be Safely Removed from Drive " & UCase(strVol)
End If
'
' Close the Handle
'
boResult = CloseVolume(lngVolHand)
If boResult = False Then
MsgBox "Error Closing Volume " & Err.LastDllError
Exit Sub
End If
Unload Me
End Sub
Private Sub Command1_Click()
Eject "k"
End Sub
Private Sub Timer1_Timer()
boTimeOut = True
End Sub
'代碼結束
'上述代碼實現了以上功能,如果U盤不是K呢?
'加點下面的代碼:
Private Function USBDISKINDEX() As String '找到U盤
Dim i As Long
For i = Asc("C") To Asc("Z")
If GetDriveType(Chr(i) + ":") = 2 Then
USBDISKINDEX = Chr(i)
End If
Next i
End Function
Private Sub Command2_Click()
Eject USBDISKINDEX '刪除U盤
End Sub

2012-10-12 19:55
程序代码:
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 2100
ClientLeft = 60
ClientTop = 450
ClientWidth = 3240
BeginProperty Font
Name = "Gulim"
Size = 9.75
Charset = 0
Weight = 700
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
LinkTopic = "Form1"
ScaleHeight = 2100
ScaleWidth = 3240
StartUpPosition = 3 '系统预设值
Begin VB.ListBox List1
BeginProperty Font
Name = "新宋体"
Size = 9
Charset = 136
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 1860
Left = 120
TabIndex = 0
Top = 120
Width = 3015
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Dim fso As FileSystemObject
Dim Dr As Drive
Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Private Const DRIVE_UNKNOWN = 0 '驱动器类型无法确定
Private Const DRIVE_NO_ROOT_DIR = 1 '驱动器根目录不存在
Private Const DRIVE_REMOVABLE = 2 '软盘驱动器或可移动盘
Private Const DRIVE_FIXED = 3 '硬盘驱动器
Private Const DRIVE_REMOTE = 4 'Network 驱动器
Private Const DRIVE_CDROM = 5 '光盘驱动器
Private Const DRIVE_RAMDISK = 6 'RAM 存储器
Private Sub Form_Load()
Dim fso As New FileSystemObject
Dim DL As Long
For Each Dr In fso.Drives
DL = GetDriveType(Dr)
Select Case DL
Case DRIVE_UNKNOWN
Debug.Print Dr.DriveLetter & "盘类型无法确定"
List1.AddItem Dr.DriveLetter & "盘类型无法确定"
Case DRIVE_NO_ROOT_DIR
Debug.Print Dr.DriveLetter & "盘不存在"
List1.AddItem Dr.DriveLetter & "盘不存在"
Case DRIVE_REMOVABLE
Debug.Print Dr.DriveLetter & "盘为软盘驱动器或可移动盘"
List1.AddItem Dr.DriveLetter & "盘为软盘驱动器或可移动盘"
Case DRIVE_FIXED
Debug.Print Dr.DriveLetter & "盘为硬盘驱动器"
List1.AddItem Dr.DriveLetter & "盘为硬盘驱动器"
Case DRIVE_REMOTE
Debug.Print Dr.DriveLetter & "盘为Network 驱动器"
List1.AddItem Dr.DriveLetter & "盘为Network 驱动器"
Case DRIVE_CDROM
Debug.Print Dr.DriveLetter & "盘为光盘驱动器"
List1.AddItem Dr.DriveLetter & "盘为光盘驱动器"
Case DRIVE_RAMDISK
Debug.Print Dr.DriveLetter & "盘为RAM 存储器"
List1.AddItem Dr.DriveLetter & "盘为RAM 存储器"
End Select
Next
End Sub

2012-10-12 19:56
2012-10-14 00:07