yhxhappy 发表于 2010-6-4 16:32:11

SetupApi 如何获取 未安装驱动的设备的 硬件ID

本帖最后由 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
Local $Class

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

_GUI()

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

                        If _ArraySearch($Class, $aClass[$i]) = -1 Then
                                ReDim $Class                                                        ;将本项设备的 Class 写进 $Class数组
                                $Class = $aClass[$i]
                                $Class = 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
                $hItem2 = GUICtrlCreateTreeViewItem($Class[$i], $hItem)
                For $a = 1 To $HardwareID
                        If $HardwareID[$a] = $Class[$i] Then
                                GUICtrlCreateTreeViewItem($HardwareID[$a], $hItem2)
                        EndIf
                Next
        Next
        GUICtrlSetState($hItem, $GUI_EXPAND)

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

kn007 发表于 2010-6-4 16:40:53

关注,等待P版的到来

pusofalse 发表于 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
                $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函数。

pusofalse 发表于 2010-6-4 17:24:39

- - |||
我把最新的SetupApi.au3贴到这里来吧,既然楼主第一次发主题帖就给帖子想了一个不错的标题,不应该浪费楼主的金钱了,貌似在UDF区下载一个附件就要30金钱。

kn007 发表于 2010-6-4 17:38:20

支持P版,口水

yhxhappy 发表于 2010-6-4 17:59:03

感谢pusofalse
还知道体贴我等穷人!
我是想用上面的方法来扫描本机的硬件ID,再与自己做的驱动光盘上INI文件里面记录的ID比对,成功则根据光盘内INI文件记录参数静默安装
不想用EVEREST的原因是它生成硬件报告耗时长,而且涉及版权问题!
不知道pusofalse对于智能驱动安装,有没有更好的点子!

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种方法。

yhxhappy 发表于 2010-6-4 19:00:17

慢慢消化!

hongshow 发表于 2010-11-22 18:54:09

学习一下........................

yongzhai 发表于 2011-10-20 10:37:24

作个记号,有空看看

chishingchan 发表于 2011-10-25 02:06:23

关于 setupapi.au3 出本书的事是刻不容缓!

xdcysten 发表于 2012-4-18 10:05:09

不错,学习了

hanz_200 发表于 2014-4-7 19:06:16

SetupApi 确实该出本书

haopp1 发表于 2014-4-22 14:30:18

消化中。。。。。。。。。。。。。。。。。。。。。。。。。

tunnyx 发表于 2014-12-28 17:52:51

支持出书.......................
页: [1] 2
查看完整版本: SetupApi 如何获取 未安装驱动的设备的 硬件ID