找回密码
 加入
搜索
查看: 1878|回复: 2

[网络通信] 【已解决】关于P版磁盘信息的一段代码为什么要执行两次,有没办法执行一次就得到

[复制链接]
发表于 2021-7-30 14:53:56 | 显示全部楼层 |阅读模式
本帖最后由 xzf680 于 2021-8-2 13:47 编辑

这是P版的一段代码,感觉不错,但为什么要执行两次才能得到结果,大家帮忙分析一下,谢谢
pusofalse帖地址:https://www.autoitx.com/forum.php?mod=viewthread&tid=9470&highlight=%B4%C5%C5%CC


#include <WinAPI.au3>
#include <GUIConstants.au3>
#include <GUIComboBox.au3>
#include <Array.au3>
CONST $tagSPDEVINFODATA = "dword Size;byte Guid[16];dword DevInst;ulong_ptr Reserved"
Global $iPhysDisk
Global $aDrive, $aUdrive[1][4] = [[0]], $aTrayItem[1] = [0]
        $aUdrive[0][0] = 0
        Redim $aUdrive[1][4]
_AddItem()
_AddItem();为什么要执行两次才能得到结果?

Func _AddItem()
        $aDrive = _EnumPhysicalDrives()        
        For $i = 1 to $aDrive[0][0]
                $sString = $aDrive[$i][1] & " - " & $aDrive[$i][2]
               ConsoleWrite($sString & @LF)
                _ArrayDisplay($aDrive)
                If bitAND($aDrive[$i][3], 2) Then
                        $aUdrive[0][0] += 1
                        Redim $aUdrive[$aUdrive[0][0] + 1][4]
                        $aUdrive[$aUdrive[0][0]][0] = $aDrive[$i][0]
                        $aUdrive[$aUdrive[0][0]][1] = $aDrive[$i][1]
                        $aUdrive[$aUdrive[0][0]][2] = $aDrive[$i][2]
                        $aUdrive[$aUdrive[0][0]][3] = $aDrive[$i][3]
                Else
                        TrayItemSetState(-1, 128)
                EndIf
        Next
EndFunc        ;==>_AddItem

Func _EnumPhysicalDrives()
        Local $sTempDriveStr, $aTempDriveArray, $hDevice
        Local $iNumDisks, $tSP_DEVINFO, $aGUID, $hDevs
        Local $sDrivePresent, $aDrivePresent, $aResult[1][4] = [[0]]

        For $i = 0 to 120
                $sTempDriveStr &= $i & ","
        Next
        $sTempDriveStr = StringTrimRight($sTempDriveStr, 1)
        $aTempDriveArray = StringSplit($sTempDriveStr, ",")

        $aGUID = _SetupDiClassGuidsFromName("DiskDrive")    
        If $aGUID[0] = 0 Then Return SetError(2, 0, $aResult)
        $hDevs = _SetupDiGetClassDevs(2, _WinAPI_GUIDFromString($aGUID[1]))
        While _SetupDiEnumDeviceInfo($hDevs, $iNumDisks, $tSP_DEVINFO)
                $iNumDisks += 1
        WEnd
        $aResult[0][0] = $iNumDisks
        Redim $aResult[$iNumDisks + 1][4]

        For $i = 1 to $aTempDriveArray[0] - 1
                $sDrive = "\\.\PhysicalDrive" & $aTempDriveArray[$i]
                $hDevice = _WinAPI_CreateFile($sDrive, 2, 6, 6, 1)
                If $hDevice = 0xFFFFFFFF Then ContinueLoop
                _DeviceCloseHandle($hDevice)
                $sDrivePresent &= $aTempDriveArray[$i] & ","
        Next
        $sDrivePresent = StringTrimRight($sDrivePresent, 1)
        $aDrivePresent = StringSplit($sDrivePresent, ",")
        For $i = 1 to $iNumDisks
                If $i > $aDrivePresent[0] Then ContinueLoop
                _SetupDiEnumDeviceInfo($hDevs, $i - 1, $tSP_DEVINFO)
                $aResult[$i][0] = "\\.\PhysicalDrive" & $aDrivePresent[$i]
                $aResult[$i][1] = _SetupDiGetDeviceRegistryProperty($hDevs, $tSP_DEVINFO, 0xC)
                $aResult[$i][1] = StringTrimRight(BinaryToString($aResult[$i][1]), 1)
                $aResult[$i][2] = _GetDiskPartitions($aDrivePresent[$i])
                $aResult[$i][3] = Number(_SetupDiGetDeviceRegistryProperty($hDevs, $tSP_DEVINFO, 32))
        Next
        
        _SetupDiDestroyDeviceInfoList($hDevs)
        Return $aResult
EndFunc        ;==>_EnumPhysicalDrives



Func _GetDiskPartitions($iPhysDriveIndex)
        Local $aDrive, $sResult, $tBuffer, $hDev, $iIndex

        $aDrive = DriveGetDrive("All")
        $tBuffer = DllStructCreate("dword[3]")
        For $i = 1 to $aDrive[0]
                $hDev = _WinAPI_CreateFile("\\.\" & $aDrive[$i], 2, 6, 6, 1, 0)
                If $hDev = 0xFFFFFFFF Then ContinueLoop
                _DeviceIoControl($hDev, 0x2D1080, 0, 0, $tBuffer, 12, 0)
                _DeviceCloseHandle($hDev)
                $iIndex = DllStructGetData($tBuffer, 1, 2)
                If $iPhysDriveIndex = $iIndex Then $sResult &= $aDrive[$i] & ","
        Next
        $tBuffer = 0
        Return (StringTrimRight($sResult, 1))
EndFunc        ;==>_GetDiskPartitions


Func _DeviceIoControl($hDevice, $iCtrlCode, $pIn, $iIn, $pOut, $iOut, $pOverlapped = 0)
        Local $iResult

        If IsDllStruct($pIn) Then $pIn = DllStructGetPtr($pIn)
        If IsDllStruct($pOut) Then $pOut = DllStructGetPtr($pOut)
        If IsDllStruct($pOverlapped) Then $pOverlapped = DllStructGetPtr($pOverLapped)
        $iResult = DllCall("Kernel32.dll", "int", "DeviceIoControl", "ptr", $hDevice, _
                        "dword", $iCtrlCode, "ptr", $pIn, "dword", $iIn, _
                        "ptr", $pOut, "dword", $iOut, "int*", 0, "ptr", $pOverlapped)
        Return SetError(_WinAPI_GetLastError(), $iResult[7], $iResult[0])
EndFunc        ;==>_DeviceIoControl


Func _SetupDiEnumDeviceInfo($hDevs, $iMemberIdx, ByRef $tSP_DEVINFO_DATA)
        Local $iResult, $pSP_DEVINFO_DATA

        If Not IsDllStruct($tSP_DEVINFO_DATA) Then
                $tSP_DEVINFO_DATA = DllStructCreate($tagSPDEVINFODATA)
                DllStructSetData($tSP_DEVINFO_DATA, "Size", DllStructGetSize($tSP_DEVINFO_DATA))
        EndIf
        $pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)
        $iResult = DllCall("Setupapi.dll", "int", "SetupDiEnumDeviceInfo", _
                        "hWnd", $hDevs, "int", $iMemberIdx, "ptr", $pSP_DEVINFO_DATA)
        Return SetError(_WinAPI_GetLastError(), 0, $iResult[0])
EndFunc        ;==>_SetupDiEnumDeviceInfo


Func _SetupDiGetClassDevs($iFlags, $pGuid = 0, $sEnumerator = "")
        Local $iResult, $sType = "str"
        If $sEnumerator = "" Then $sType = "ptr"

        If IsDllStruct($pGuid) Then $pGuid = DllStructGetPtr($pGuid)
        $iResult = DllCall("Setupapi.dll", "hWnd", "SetupDiGetClassDevs", _
                        "ptr", $pGuid, $sType,$sEnumerator, "hWnd", 0, "dword", $iFlags)
        Return SetError(_WinAPI_GetLastError(), 0, $iResult[0])
EndFunc        ;==>_SetupDiGetClassDevs

Func _SetupDiDestroyDeviceInfoList($hDevs)
        Local $iResult
        $iResult = DllCall("Setupapi.dll", "int", "SetupDiDestroyDeviceInfoList", "ptr", $hDevs)
        Return SetError(_WinAPI_GetLastError(), 0, $iResult[0])
EndFunc        ;==>_SetupDiDestroyDeviceInfoList


Func _SetupDiRemoveDevice($hDevs, $pSP_DEVINFO_DATA)
        Local $iResult

        If IsDllStruct($pSP_DEVINFO_DATA) Then
                $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
        EndIf
        $iResult = DllCall("Setupapi.dll", "int", "SetupDiRemoveDevice", _
                        "hWnd", $hDevs, "ptr", $pSP_DEVINFO_DATA)
        Return SetError(_WinAPI_GetLastError(), 0, $iResult[0])
EndFunc        ;==>_SetupDiRemoveDevice



Func _SetupDiClassGuidsFromName($sClassName)
        Local $tBuffer, $pBuffer, $aResult[1] = [0], $iResult, $tagBuffer, $iSysError

        $iResult = DllCall("Setupapi.dll", "int", "SetupDiClassGuidsFromName", _
                        "str", $sClassName, "ptr", 0, "dword", 0, "dword*", 0)
        $aResult[0] = $iResult[4]
        Redim $aResult[$iResult[4] + 1]
        For $i = 1 to $iResult[4]
                $tagBuffer &= "byte[16];"
        Next
        $tBuffer = DllStructCreate($tagBuffer)
        $pBuffer = DllStructGetPtr($tBuffer)
        $iResult = DllCall("Setupapi.dll", "int", "SetupDiClassGuidsFromName", _
                        "str", $sClassName, "ptr", $pBuffer, _
                        "dword", $iResult[4], "dword*", 0)
        If $iResult[0] = 0 Then $iSysError = _WinAPI_GetLastError()
        For $i = 1 to $iResult[4]
                $aResult[$i] = _WinAPI_StringFromGUID(DllStructGetPtr($tBuffer, $i))
        Next
        $tBuffer = 0
        Return SetError($iSysError, 0, $aResult)
EndFunc        ;==>_SetupDiClassGuidsFromName



Func _SetupDiGetDeviceRegistryProperty($hDevs, $pSP_DEVINFO_DATA, $iProperty)
        Local $iResult, $tBuffer, $pBuffer, $vResult, $iSysError

        If IsDllStruct($pSP_DEVINFO_DATA) Then
                $pSP_DEVINFO_DATA = DllStructGetPtr($pSP_DEVINFO_DATA)
        EndIf
        $iResult = DllCall("Setupapi.dll", "int", "SetupDiGetDeviceRegistryProperty", _
                        "hWnd", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
                        "dword", $iProperty, "int*", 0, "ptr", 0, "dword", 0, "int*", 0)
        $tBuffer = DllStructCreate("byte[" & $iResult[7] & "]")
        $pBuffer = DllStructGetPtr($tBuffer)
        $iResult = DllCall("Setupapi.dll", "int", "SetupDiGetDeviceRegistryProperty", _
                        "hWnd", $hDevs, "ptr", $pSP_DEVINFO_DATA, _
                        "dword", $iProperty, "int*", 0, "ptr", $pBuffer, _
                        "dword", $iResult[7], "int*", 0)
        If $iResult[0] = 0 Then $iSysError = _WinAPI_GetLastError()
        $vResult = DllStructGetData($tBuffer, 1)
        $tBuffer = 0
        Return SetError($iSysError, $iResult[4], $vResult)
EndFunc        ;==>_SetupDiGetDeviceRegistryProperty


Func _DeviceCloseHandle($hDevice)
        Local $iResult = DllCall("Kernel32.dll", "int", "CloseHandle", "long", $hDevice)
        Return $iResult[0] <> 0
EndFunc        ;==>_DeviceCloseHandle




另外一个问题
If bitAND($aDrive[$i][3], 2) Then
这里是怎么判断的USB磁盘,如本地磁盘又怎么判断?

然后我测试注释了        _ArrayDisplay($aDrive)     添加一行 ConsoleWrite($sString & @LF)    居然取不到结果了,怪事!!!
发表于 2021-8-1 17:19:20 | 显示全部楼层
问题1:先dllopen,再dllcall。
问题2:按照你给的代码,2、3代表可移动磁盘,1是本地磁盘。
问题3:问题1解决了,这个问题应该就解决了。
没有实际测试,需要你自己试验。
 楼主| 发表于 2021-8-2 13:46:13 | 显示全部楼层
haijie1223 发表于 2021-8-1 17:19
问题1:先dllopen,再dllcall。
问题2:按照你给的代码,2、3代表可移动磁盘,1是本地磁盘。
问题3:问题 ...

原来是这样,学习了,谢谢发哥
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-23 03:03 , Processed in 0.069061 second(s), 19 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表