找回密码
 加入
搜索
查看: 20127|回复: 17

[系统综合] SetupApi 如何获取 未安装驱动的设备的 硬件ID

 火.. [复制链接]
发表于 2010-6-4 16:32:11 | 显示全部楼层 |阅读模式
本帖最后由 yhxhappy 于 2010-6-4 19:00 编辑

第一次发贴, 标题什么起都觉得怪

以下代码是我修改后发上来的,本意并不是取得设备名并显示出来,只供参考
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <GuiTreeView.au3>
#include <SetupApi.au3>

Global $aClass = _CM_Enumerate_Classes()
Local $HardwareID[1][2]
Local $Class[1][2]

_HardwareScan()
_ArraySort($Class)
_ArraySort($HardwareID)

_GUI()

Func _HardwareScan()
        Local $Noclass = "{8ECC055D-047F-11D1-A537-0000F8753ED1}";|非即插即用驱动程序
        For $i = 1 To $aClass[0][0]
                If $aClass[$i][0] = $Noclass Then ContinueLoop
                $Device = _CM_Enum_Device_Info($aClass[$i][0])                                                ;根据 Class 来枚举子项设备
                If $Device[0][0] = 0 Then ContinueLoop                                                                ;如果该 Class 下的子设备为 0 则跳过
                For $a = 1 To $Device[0][0]
                        $iStatus = _CM_Get_DevNode_Status($Device[$a][2])                                ;根据设备号来判断设备是否在 设备管理器 内显示出来 $DN_NO_SHOW_IN_DM
                        If bitAND($iStatus, $DN_NO_SHOW_IN_DM) Then ContinueLoop
                        
                        ReDim $HardwareID[UBound($HardwareID)+1][5]
                        $HardwareID[UBound($HardwareID)-1][1] = $aClass[$i][1]                        ;将设备所属的 Class 写进 $Hardware_ID[0]
                        $HardwareID[UBound($HardwareID)-1][0] = $Device[$a][0]                        
                        $HardwareID[0][0] = UBound($HardwareID)-1

                        If _ArraySearch($Class, $aClass[$i][1]) = -1 Then
                                ReDim $Class[UBound($Class)+1][2]                                                        ;将本项设备的 Class 写进 $Class数组
                                $Class[UBound($Class)-1][0] = $aClass[$i][1]
                                $Class[0][0] = UBound($Class)-1
                        EndIf
                Next
        Next
EndFunc

Func _GUI()
        $FORM = GUICreate("", 600, 700)
        $Tree = GUICtrlCreateTreeView(0, 0, 600, 700)

        GUISetState(@SW_SHOW) ; 显示窗口

        $hItem = GUICtrlCreateTreeViewItem(@ComputerName, $Tree)
        For $i = 1 To $Class[0][0]
                $hItem2 = GUICtrlCreateTreeViewItem($Class[$i][0], $hItem)
                For $a = 1 To $HardwareID[0][0]
                        If $HardwareID[$a][1] = $Class[$i][0] Then
                                GUICtrlCreateTreeViewItem($HardwareID[$a][0], $hItem2)
                        EndIf
                Next
        Next
        GUICtrlSetState($hItem, $GUI_EXPAND)

        ;运行窗口直到用户关闭
        While 1
                If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
        WEnd
EndFunc
上面的代码 我是先枚举系统内全部可用的CLASS,再根据CLASS枚举全部的硬件,最后判断该硬件是否在设备管理器内显示,是则写进数组最后显示到GUI上
现在碰到的问题是,不知道如何识别 未安装驱动的设备。虽然在设备管理器里面是显示“未知设备”里面,但是查看注册表该设备并不属于任何CLASS,所以通过枚举CLASS的方法行不通
现在只能通过别的方式枚举设备了
还请各位大大能解答一下

评分

参与人数 1金钱 +10 收起 理由
afan + 10 感谢主动将修改帖子分类为[已解决],请继续 ...

查看全部评分

发表于 2010-6-4 16:40:53 | 显示全部楼层
关注,等待P版的到来
发表于 2010-6-4 17:16:38 | 显示全部楼层
#include <SetupAPI.au3>

Local $sDelims = Random(1, 1000), $sDevices

; Scan for hardware changes.
_CM_Scan_Device_Changes("")

_FindDeviceRecur(_CM_Locate_DevNode(""))

$sDevices = StringSplit(StringTrimRight($sDevices, StringLen($sDelims)), $sDelims, 1)
_Arraydisplay($sDevices)


Func _FindDeviceRecur($hDevInst)
        Local $aChild, $sDescr, $sClass

        $aChild = _CM_Enumerate_Children($hDevInst)
        For $i = 1 To $aChild[0]
                $hDevInst = _CM_Locate_DevNode($aChild[$i])
                $sClass = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_CLASS)
                If ($sClass = "") Then
                        $sDescr = _CM_Get_Device_Display_Name_Ex($hDevInst)
                        $sDevices &= $sDescr & ", " & $aChild[$i] & $sDelims
                EndIf
                _FindDeviceRecur($hDevInst)
        Next
EndFunc        ;==>_FindDeviceRecur
_CM_Enum_Device_Info的效率不如上面的快,因为它事先要创建设备信息集合,然后依次枚举集合中的设备,这是2个耗时的指令。

以上代码,_FindDeviceRecur从设备树根部开始,枚举所有设备,并获取设备的类别名称(CM_DRP_CLASS),如果类别名称为空,则可以认为这是没有安装驱动的设备。

开头那句_CM_Scan_Device_Changes如同设备管理器中的“扫描检测硬件改动”,可以检测到已经卸载的设备,这也是个耗时的指令。

最后,_Arraydisplay中显示的就是没有加载驱动程序的设备的名称及设备ID。
请下载最新的SetupApi.au3,原本的库中没有_CM_Get_Device_Display_Name_Ex函数。

评分

参与人数 1金钱 +100 贡献 +20 收起 理由
kn007 + 100 + 20

查看全部评分

发表于 2010-6-4 17:24:39 | 显示全部楼层
- - |||
我把最新的SetupApi.au3贴到这里来吧,既然楼主第一次发主题帖就给帖子想了一个不错的标题,不应该浪费楼主的金钱了,貌似在UDF区下载一个附件就要30金钱。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2010-6-4 17:38:20 | 显示全部楼层
支持P版,口水
 楼主| 发表于 2010-6-4 17:59:03 | 显示全部楼层
感谢pusofalse
还知道体贴我等穷人!
我是想用上面的方法来扫描本机的硬件ID,再与自己做的驱动光盘上INI文件里面记录的ID比对,成功则根据光盘内INI文件记录参数静默安装
不想用EVEREST的原因是它生成硬件报告耗时长,而且涉及版权问题!
不知道pusofalse对于智能驱动安装,有没有更好的点子!
发表于 2010-6-4 18:14:06 | 显示全部楼层
SetupAPI.au3 提供3种驱动更新方式。
1、_CM_Install_DevInst_Ex,与设备管理器安装驱动的方式相同,可以指定光盘安装,也可以手动选择。
2、_CM_Install_Device_Driver,除了兼容第一种方式外,还可以指定多种更新标识,比如 静默安装。
3、_CM_Update_PnP_Device,指定ini文件,ini中定义安装参数。你所说的应该适于用这种方式安装。

_CM_Update_PnP_Device原型:
_CM_Update_PnP_Device($sDeviceID, $sInfPath, $iFlags, $hWnd = 0)

$sDeviceID - 要更新驱动的设备的硬件ID
$sInfPath - INF路径。
$iFlags - 安装标识,一般指定为0即可。更多选项请参考http://msdn.microsoft.com/en-us/library/ff553534(VS.85).aspx
$hWnd - 父窗口句柄,可以指定为0。

硬件ID不同于设备范例ID,要获取一个设备的硬件ID,调用_CM_Get_DevNode_Registry_Property,传递CM_DRP_HARDWAREID属性值。

_CM_Update_PnP_Device,只能更新即插即用设备,对于非即插即用设备,用上面2种方法。

评分

参与人数 1金钱 +30 收起 理由
afan + 30

查看全部评分

 楼主| 发表于 2010-6-4 19:00:17 | 显示全部楼层
慢慢消化!
发表于 2010-11-22 18:54:09 | 显示全部楼层
学习一下........................
发表于 2011-10-20 10:37:24 | 显示全部楼层
作个记号,有空看看
发表于 2011-10-25 02:06:23 | 显示全部楼层
关于 setupapi.au3 出本书的事是刻不容缓!
发表于 2012-4-18 10:05:09 | 显示全部楼层
不错,学习了
发表于 2014-4-7 19:06:16 | 显示全部楼层
SetupApi 确实该出本书
发表于 2014-4-22 14:30:18 | 显示全部楼层
消化中。。。。。。。。。。。。。。。。。。。。。。。。。
发表于 2014-12-28 17:52:51 | 显示全部楼层
支持出书.......................
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-12-24 02:14 , Processed in 0.086091 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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