rally 发表于 2021-1-25 19:58:50

模仿磁盘管理显示接入硬盘-已解决

本帖最后由 rally 于 2021-1-26 21:03 编辑

想做个类似磁盘管理监控多块硬盘拔插,像磁盘管理一样实时更新列表。奈何菜鸟还不知道从哪入手。参考了"CoProc.au3“多进程处理方式。总不完美,
#NoTrayIcon
#include "CoProc.au3"

#region 主程序区域
#include <GUIConstants.au3>
$Form1 = GUICreate("Multiple File Download", 622, 300, 192, 300)

$label1 = GUICtrlCreateLabel("现在接入硬盘数量:",5,5,140,30)
GUICtrlSetFont(-1, 10, 400, 0, "Arial")
$label2 = GUICtrlCreateLabel("0",145,5,120,30)
GUICtrlSetFont(-1, 10, 400, 0, "Arial")

$edit = GUICtrlCreateEdit("",50,50,400,220,$ES_AUTOHSCROLL)

$Button1 = GUICtrlCreateButton("写入随机数据", 480, 120, 81, 25)
$Button2 = GUICtrlCreateButton("Test",480, 60, 81, 25)

$iPidSmall = _CoProc("Small") ;开启子进程,子进程将执行Small()函数,$iPidSmall得到的是子进程的PID
GUISetState(@SW_SHOW)

_CoProcReciver("Reciver") ;注册Reciver()函数来接收子进程传递过来的消息

While 1
    $msg = GuiGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
      ExitLoop
                AdlibUnRegister("Reciver")

    Case $msg = $Button1
          For $i=1 to 20
             $n = Random(1,999)
             GUICtrlSetData($edit,$n & @CRLF,'')
      Next

    Case $msg = $Button2
            MsgBox(0,"","Test ok")
    EndSelect
WEnd
FileDelete(@TempDir & "\smalltest.tmp")
FileDelete(@TempDir & "\bigtest.tmp")
Exit

Func Reciver($vParameter)
      GUICtrlSetData($label2,$vParameter)
EndFunc
#endregion

Func Small()
    While 1
          Local $objWMI = ObjGet('Winmgmts:{ImpersonationLevel=Impersonate,AuthenticationLevel=PktPrivacy,(Debug)}!\\.\root\CIMV2')
      Local $objClass = $objWMI.InstancesOf('Win32_DiskDrive')
      Local $count = $objClass.Count
          _CoProcSend($gi_CoProcParent,$count)
          sleep(200)
    WEnd
EndFunc

afan 发表于 2021-1-25 20:54:36

这个既不用多进程,更不用循环检测。注册 WM_DEVICECHANGE 消息,简单几行代码。

rally 发表于 2021-1-25 21:20:13

afan 发表于 2021-1-25 20:54
这个既不用多进程,更不用循环检测。注册 WM_DEVICECHANGE 消息,简单几行代码。

我查了WM_DEVIECECHANGE,好像要HOOK到界面才行,无奈看不懂,能不能指点一下几行代码学习一下。麻烦版主大大

rally 发表于 2021-1-25 21:21:15

上次也是查自动获取U盘提示的,也有看到afan大大提到WM_DEVIECECHANGE,没有学习到

afan 发表于 2021-1-25 22:31:29

GUICreate('磁盘监控')
Global $iLb = GUICtrlCreateLabel('', 50, 10, 300, 20, 0x201)
Global $iEdit = GUICtrlCreateEdit('', 50, 30, 300, 320)
_DeviceInfo()
GUISetState()
GUIRegisterMsg(537, '_WM_DEVICECHANGE')

While GUIGetMsg() <> -3
WEnd
Exit

Func _DeviceInfo()
        Local $iMask = DllCall('kernel32.dll', 'dword', 'GetLogicalDrives')
        Local $td = DllStructCreate('dword;dword;int')
        Local $hDevice, $aRt, $nDrive, $nMax, $sInfo = ''
        For $ii = 0 To 25
                If Not BitAND(BitShift($iMask, $ii), 1) Then ContinueLoop
                $aRt = DllCall('kernel32.dll', 'hwnd', 'CreateFile', 'str', '\\.\' & Chr(65 + $ii) & ':', 'dword', 0, 'dword', 0, 'ptr', 0, 'dword', 3, 'dword', 128, 'ptr', 0)
                $hDevice = $aRt
                DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'hwnd', $hDevice, 'dword', 0x2D1080, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($td), 'dword', DllStructGetSize($td), 'dword*', 0, 'ptr', 0)
                DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $hDevice)
                $nDrive = DllStructGetData($td, 2)
                If $nMax < $nDrive Then $nMax = $nDrive
                $sInfo &= Chr(65 + $ii) & ': 硬盘 ' & $nDrive & ', 分区 ' & DllStructGetData($td, 3) & @CRLF
        Next
        GUICtrlSetData($iLb, '当前接入硬盘数量:' & $nMax + 1)
        GUICtrlSetData($iEdit, $sInfo)
        GUICtrlSetState($iLb, 256)
EndFunc   ;==>_DeviceInfo
Func _WM_DEVICECHANGE($hWnd, $Msg, $wParam, $lParam)
        Switch $wParam
                Case 0x8000, 0x8004
                        _DeviceInfo()
        EndSwitch
EndFunc   ;==>_WM_DEVICECHANGE

rally 发表于 2021-1-26 13:15:56

模仿磁盘管理显示接入硬盘 - 已解决

本帖最后由 rally 于 2021-1-26 13:17 编辑

非常感谢版主大大,好好学习一下:face (10):

rally 发表于 2021-1-26 16:18:40

本帖最后由 rally 于 2021-1-26 16:20 编辑

afan 发表于 2021-1-25 22:31

版主大大,我在测试的时候,发现,如果硬盘没有分区,接上去是不会有显示的,这个WM_DEVICECHANGE只能检测已经分区的硬盘吗?

afan 发表于 2021-1-26 20:15:59

rally 发表于 2021-1-26 16:18
版主大大,我在测试的时候,发现,如果硬盘没有分区,接上去是不会有显示的,这个WM_DEVICECHANGE只能检 ...


消息应该都是有的,只是获取磁盘信息是通过盘符逐盘获取的,不然哪来的对应信息。
没有未分区的磁盘,无法测试。也不知道获取未分区磁盘的意义,难不成还想操作分区格式化… 如此也犯不着检测消息那么及时,直接干就是了

rally 发表于 2021-1-26 21:02:33

嗯,后面我又尝试了一下,在不加   Switch $wParam   Case 0x8000, 0x8004 情况下,只要有消息就判断一下是不是硬盘接入,这样没那么直接,也能达到效果。谢谢版主大大的关照
页: [1]
查看完整版本: 模仿磁盘管理显示接入硬盘-已解决