找回密码
 加入
搜索
查看: 13194|回复: 15

[系统综合] 请问关于AHCI模式下的硬盘ID获取不到的问题

 火.. [复制链接]
发表于 2012-2-7 13:38:58 | 显示全部楼层 |阅读模式
本帖最后由 kxing 于 2012-2-8 14:39 编辑

请问有些硬盘为什么获取不到序列号呢
用过了本坛所有代码都是获取不到。
cpu序列号就正常。
还望高手指点指点!!!
发表于 2012-2-7 14:42:18 | 显示全部楼层
[au3]#Include <WinAPIEx.au3>
_Winapi_GetDiskSerialNumber[/au3]
发表于 2012-2-7 16:14:45 | 显示全部楼层
来学习了……
 楼主| 发表于 2012-2-7 18:23:40 | 显示全部楼层
多谢,我在帮助里面没找到这个函数呢
 楼主| 发表于 2012-2-7 19:11:08 | 显示全部楼层
表达错了,应该是获取硬盘ID。
听说现在AHCI的硬盘都无法获取到硬盘ID,请问是这样的吗
发表于 2012-2-7 19:23:27 | 显示全部楼层
回复 1# kxing

试试这个呢?------来源于本论坛:


#include <WinAPI.au3>
$tSCIP = 0
$tSCOP = 0
$tQuery = 0
$tDescr = 0

Local $num=_GetDiskNum(0) ;这个0是硬盘的序号。 有几个硬盘就是几减1。 比如,想获取第三个硬盘的硬盘号,则是_GetDiskNum(2)
MsgBox(0,"",$num)


Func _GetDiskNum($DiskID = "0")
        $sPhysDisk="\\.\PhysicalDrive"&$DiskID
        Const $IOCTL_STORAGE_BASE = 0x2D
        Const $IOCTL_STORAGE_QUERY_PROPERTY = _MakeCtrlCode($IOCTL_STORAGE_BASE, 0x500)
        Const $DFP_RECEIVE_DRIVE_DATA = 0x7C088
        Const $tagSTORAGEPROPERTYQUERY = "int PropertyId;int QueryType;byte AdditionalParams"
        Const $tagSTORAGEDEVICEDESCRIPTOR = "ulong Version;ulong Size;byte DeviceType;" & _
                        "byte DeviceTypeModifier;byte RemovableMedia;" & _
                        "byte CommandQueueing;ulong VendorIdOffset;" & _
                        "ulong ProductIdOffset;ulong ProductRevisionOffset;" & _
                        "ulong SerialNumberOffset;int BusType;" & _
                        "ulong RawPropertiesLength;byte RawDeviceProperties"
        Const $tagDRIVERSTATUS = "byte DriverError;byte IDEStatus;byte Reserved1[2];dword Reserved2[2]"
        Const $tagIDEREGS = "byte Features;byte SectorCount;byte SectorNumber;byte CylLow;" & _
                        "byte CylHigh;byte DriveHead;byte Command;byte Reserved"
        Const $tagSENDCMDOUTPARAMS = "dword Size;" & $tagDRIVERSTATUS
        Const $tagSENDCMDINPARAMS = "dword Size;" & $tagIDEREGS & ";byte DriveNumber;" & _
                        "byte Reserved1[3];dword Reserved2[4];byte Buffer"
        $hDisk = _WinAPI_CreateFile($sPhysDisk, 2, 6, 6, 1)
        If $hDisk = -1 Then
        Return @error
        EndIf
        
        $tSCIP = DllStructCreate($tagSENDCMDINPARAMS)
        $tSCOP = DllStructCreate($tagSENDCMDOUTPARAMS & ";char Buffer[1024]")
        $tQuery = DllStructCreate($tagSTORAGEPROPERTYQUERY)
        $tDescr = DllStructCreate($tagSTORAGEDEVICEDESCRIPTOR)
        DllStructSetData($tQuery, "PropertyId", 0)
        DllStructSetData($tQuery, "QueryType", 0)
        $iResult = _DeviceIoControl($hDisk, $IOCTL_STORAGE_QUERY_PROPERTY, _
                $tQuery, DllStructGetSize($tQuery), _
                $tDescr, DllStructGetSize($tDescr))
        If $iResult = 0 Then
                Return @error
        EndIf
        
        If DllStructGetData($tDescr, "BusType") = 2 Then
        DllStructSetData($tSCIP, "Command", 0xA1)
        Else
                DllStructSetData($tSCIP, "Command", 0xEC)
        EndIf
        
        $iResult = _DeviceIoControl($hDisk, $DFP_RECEIVE_DRIVE_DATA, _
                $tSCIP, DllStructGetSize($tSCIP), _
                $tSCOP, DllStructGetSize($tSCOP))
        If $iResult = 0 Then
                MsgBox(16,"错误!","_DeviceIoControl fails, error code: " & @error ,5)
                Exit
        EndIf
        
        Dim $sSerialNum
        For $i = 21 to 40 Step 2
        $sSerialNum &= DllStructGetData($tSCOP, "Buffer", $i + 1)
        $sSerialNum &= DllStructGetData($tSCOP, "Buffer", $i)
        Next
        $sSerialNum = StringReplace($sSerialNum, " ", "")
        ;输出显示
        ;Msgbox(0, "", $sPhysDisk & "'s serial number: " & $sSerialNum)
        Return $sSerialNum
        _WinAPI_CloseHandle($hDisk)
EndFunc


Func _MakeCtrlCode($iDevType, $iFunction, $iMethod = 0, $iAccess = 0)
        Return bitOR(bitShift($iDevType,-16),bitShift($iAccess, -14),bitShift($iFunction, -2), $iMethod)
EndFunc        ;==>_MakeCtrlCode

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
发表于 2012-2-7 20:29:35 | 显示全部楼层
本帖最后由 netegg 于 2012-2-7 20:32 编辑

回复 6# boyhong
这个就是那个函数的原型,kxing要的可能是harddisk0,harddisk1,。。。这些东西,或者是部署linux前面的那些hd0,hd1,一类的玩意
发表于 2012-2-7 21:29:56 | 显示全部楼层
下面这个是能显示hd0,hd1,hd2的
GetPartionMsg("", 1)        ;GetPartionMsg 的第一个参数可以是 USB、IDE 等;如果不带任何参数,则是检测所有磁盘分区
                                                ;第二个参数可以是 1、0,1 表示 TRUE,0 表示 FALSE;如果第一个参数为空,则第二个必需为 1
 
Func GetPartionMsg($Interface, $b)
        $objWMIService = ObjGet("winmgmts:\\.\root\cimv2")
        $colItems = $objWMIService.ExecQuery ("Select * from Win32_LogicalDiskToPartition")
                
        $DiskInfo = ""
        $DiskInfoCombo = ""
        For $objItem In $colItems
                                MsgBox(64,"",$objItem.Dependent)
                $DiskFH = StringLeft(StringRight($objItem.Dependent, 3), 2)
                                $PartNum = QueryDiskNum($DiskFH)
                $PartMsg = QueryPartitionVolume($DiskFH)
                If $Interface <> "" Then
                        If $b = 1 Then
                                If StringMid($PartNum, 2, 3) = $Interface Then
                                        $DiskInfo = $DiskInfo & $PartNum & $DiskFH & $PartMsg & @CRLF
                                EndIf
                        ElseIf $b = 0 Then
                                If StringMid($PartNum, 2, 3) <> $Interface Then
                                        $DiskInfo = $DiskInfo & $PartNum & $DiskFH & $PartMsg & @CRLF
                                EndIf
                        EndIf
                Else
                        $DiskInfo = $DiskInfo & $PartNum & $DiskFH & $PartMsg & @CRLF
                EndIf
        Next
        MsgBox(64, "磁盘信息", $DiskInfo)
EndFunc   ;==>GetPartionMsg
 
Func QueryDiskInterface($n)
        $objWMIService = ObjGet("winmgmts:\\.\root\cimv2")
        $colItems = $objWMIService.ExecQuery ("Select * from Win32_DiskDrive Where Index=" & $n)
        For $objItem In $colItems
                Return $objItem.InterfaceType
        Next
EndFunc   ;==>QueryDiskInterface
 
Func QueryPartitionVolume($v)
        $objWMIService = ObjGet("winmgmts:\\.\root\cimv2")
        $colItems = $objWMIService.ExecQuery ("Select * from Win32_LogicalDisk Where DeviceID='" & $v & "'")
        For $objItem In $colItems
                Return $objItem.VolumeName & "" & $objItem.FileSystem & "_" & CalcKMG($objItem.Size) & "_" & $objItem.Description
        Next
EndFunc   ;==>QueryPartitionVolume
 
Func QueryDiskNum($d)
        $objWMIService = ObjGet("winmgmts:\\.\root\cimv2")
        $colItems = $objWMIService.ExecQuery ("Associators of {win32_LogicalDisk.DeviceID='" & $d & "'} where ResultClass = Win32_DiskPartition")
        For $colItem In $colItems
                Return "(" & QueryDiskInterface($colItem.DiskIndex) & ":hd" & $colItem.DiskIndex & ")" 
        Next
EndFunc   ;==>QueryDiskNum
 
Func CalcKMG($n)
        If $n < 1024 Then
                Return $n & "Byte" 
        ElseIf $n < 1048576 Then
                Return Round($n / 1024, 2) & "KB" 
        ElseIf $n < 1073741824 Then
                Return Round($n / 1048576, 2) & "MB" 
        Else
                Return Round($n / 1073741824, 2) & "GB" 
        EndIf
EndFunc   ;==>CalcKMG
 楼主| 发表于 2012-2-7 21:43:24 | 显示全部楼层
回复 8# seniors


   
我是想获取硬盘的ID呢,不是盘符。。。

另外 boyhong 的估计不行,我在本论坛所有能获取的都尝试过了。。。
发表于 2012-2-7 23:15:49 | 显示全部楼层
序列号在哪看?P版的帖子试过没?
发表于 2012-2-8 00:31:18 | 显示全部楼层
楼主解决了吗?
 楼主| 发表于 2012-2-8 14:34:02 | 显示全部楼层
没啊,只要把AHCI模式改成IDE就正常获取到硬盘的ID
回afan,应该不算是序列号,是ID。
 楼主| 发表于 2012-2-8 14:39:29 | 显示全部楼层
afan大说的是这个帖子吧,都试过了。不行!!!
http://autoitx.com/forum.php?mod ... hlight=%D3%B2%C5%CC
发表于 2012-2-8 17:04:15 | 显示全部楼层
AHCI下很多专业软件都无法获取硬盘信息 比如通电时间 缓存大小 至于序列号这个没关注  如果实在不能获取  我觉得也可以理解。
 楼主| 发表于 2012-2-9 11:17:22 | 显示全部楼层
那就麻烦了,软件需要通过获取硬盘id来绑定使用。。。
获取不到就没辙了!!!!!!!
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-11-15 09:45 , Processed in 0.076511 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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