本帖最后由 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) 居然取不到结果了,怪事!!!
|