yhxhappy 发表于 2010-10-30 10:26:25

[已解决] SetupAPI 在64位系统下获取 设备驱动版本 问题

本帖最后由 yhxhappy 于 2010-11-1 12:38 编辑

现已通过其它方法解决取得驱动版本的问题。

如题!#include <SetupApi.au3>

Local $hDevs, $tDevInfo, $aDisplay = []
$hDevs = _SetupDiGetClassDevs($DIGCF_PRESENT, "Display")
While _SetupDiEnumDeviceInfo($hDevs, $aDisplay, $tDevInfo)
      $aDisplay += 1
      $sDescr = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, $SPDRP_DEVICEDESC)
      $sName = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, $SPDRP_FRIENDLYNAME)
      If $sName <> "" Then $sDescr = $sName
      Redim $aDisplay[$aDisplay + 1]
      $aDisplay[$aDisplay] = $sDescr      ; 显卡型号
      $aDisplay[$aDisplay] = _SetupDiGetDeviceInstanceID($hDevs, $tDevInfo) ; 设备范例ID
WEnd
_SetupDiDestroyDeviceInfoList($hDevs)

$Version = Get_Driver_Version($aDisplay)
MsgBox(0, "", "显卡型号:" & $aDisplay & @CRLF & "驱动版本:" & $Version & @CRLF & "范例ID:" & $aDisplay)
Exit


Func Get_Driver_Version($InstanceID)       
        If $InstanceID = "" Then Return "Unknown"
        Local $hDevs,$tDevInfo, $tDrvInfo, $tDrvDetail, $sInf, $sDateVer
       
        _SetupDiCreateDeviceDevs($InstanceID, $hDevs, $tDevInfo)
        _SetupDiBuildDriverInfoList($hDevs, $tDevInfo)
        _SetupDiSelectBestCompatDrv($hDevs, $tDevInfo)
        _SetupDiGetSelectedDriver($hDevs, $tDevInfo, $tDrvInfo)
        _SetupDiGetDriverInfoDetail($hDevs, $tDevInfo, $tDrvInfo, $tDrvDetail)
                       
        $sInf = DllStructGetData($tDrvDetail, "InfFileName")
        $sDateVer = IniRead($sInf, "Version", "DriverVer", "Unknown")
        If $sDateVer = "Unknown" Or $sDateVer = "" Then
                Return "Unknown"
        Else
                $VersionArray = StringSplit($sDateVer, ",", 1)
                If $VersionArray = 1 Then
                        Return "Unknown"
                Else
                        While 1
                                If StringLeft($VersionArray, 1) <> " " Then ExitLoop
                                $VersionArray = StringTrimLeft($VersionArray, 1)
                        WEnd
                        Return $VersionArray
                EndIf
        EndIf
EndFunc以上部分脚本截取自pusofalse写的”FSeven_V47 设备管理器“,在32位的WINDOWS下可以通过设备范例ID取得驱动版本,但在64位系统下获取失败。
在系统设备管理器里有版本信息,不了解系统是如何获取的。
请pusofalse以及各位大大帮我看看!

yhxhappy 发表于 2010-10-30 15:26:51

没人看吗,自己顶!

hzxymkb 发表于 2010-11-3 10:30:23

回复 1# yhxhappy

楼主能提供解决方法上来吗?

yhxhappy 发表于 2010-11-6 13:32:29

本帖最后由 yhxhappy 于 2010-11-6 13:37 编辑

回复 3# hzxymkb

我发的帖子还是第一次被版主打分呢,很高兴。
下面是我解决的代码,有部分是从 pusofalse 写的”FSeven_V47 设备管理器“ 搬的
还是以取显卡驱动版本为例。我在32位和64位的WIN_2K, WIN_XP, WIN_VISTA, WIN_2003, WIN_2008, WIN_2008R2, WIN_7验证通过。#include <SetupApi.au3>

FindDeviceRecur(_CM_Locate_DevNode(""))

Func FindDeviceRecur($hDevInst)
        $aChild = _CM_Enumerate_Children($hDevInst)       
        For $i = 1 To $aChild
                $hDevInst = _CM_Locate_DevNode($aChild[$i])
                $Class = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_CLASS)
                $sDescr = _CM_Get_DevNode_Registry_Property($hDevInst, 1)
                $Version = Get_Driver_Version($hDevInst)
                If $Class = "Display" Then MsgBox(0,"","显卡型号:" & $sDescr & @CRLF & @CRLF & "驱动版本:" & $Version)
               ;此处只是为了取显卡的信息,所以加了判断,去掉可以取所有硬件驱动版本信息
      FindDeviceRecur($hDevInst)
        Next
EndFunc


Func Get_Driver_Version($hDevInst)
       
        $ClassGUID = _CM_Get_DevNode_Registry_Property($hDevInst, 10)
       
        If $ClassGUID = "" Then Return "Unknown"
        If @OSArch = "X86" Then
                $Reg = "HKLM\SYSTEM\ControlSet001\Control\Class\"
        Else
                $Reg = "HKLM64\SYSTEM\ControlSet001\Control\Class\"
        EndIf
       
        $Version = RegRead($Reg & $ClassGUID, "DriverVersion")

        If $Version = "" Then
                Return "Unknown"
        Else
                Return $Version
        EndIf
EndFunc

user3000 发表于 2011-11-12 22:50:37

学习了!
谢谢分享

maxf4 发表于 2014-8-6 09:34:40

回复 4# yhxhappy

请问如果我的电脑里有一些驱动,他们的类名是一样的,我如何筛选他们【比如类名为system,一搜一大堆】

yhxhappy 发表于 2014-8-6 14:35:07

回复 6# maxf4


    不太明白你问的意思。下面是一个类似设备管理器的脚本供参考#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <GuiTreeView.au3>
#include <SetupApi.au3>


$DMGUI = GUICreate("Device Manager", 800, 600)

$DMTree = GUICtrlCreateTreeView(1, 1, 800, 600)
_HardwareScan()

GUISetState()

While 1
   If GUIGetMsg() = -3 Then Exit
WEnd

Func _HardwareScan()                                                                        ;扫描本机硬件信息并将信息添加至 TREE 控件
   Global $Hardware, $Class, $HWNum = 1

   _FindDeviceRecur(_CM_Locate_DevNode(""))

   ReDim $Hardware[$HWNum]
   $Hardware = $HWNum-1

   _ArraySort($Hardware, 0, 1, 0, 1)
   _GUICtrlTreeView_DeleteAll($DMTree)

   Local $ClassItemString = "", $hItem2, $icon, $v
   $hItem = GUICtrlCreateTreeViewItem(@ComputerName, $DMTree)                                                        ;计算机名添加进 TREE控件
   For $a = 1 To $Hardware
          $GUID = $Hardware[$a]
          $GUIDName = $Hardware[$a]
          If Not StringInStr($ClassItemString, $GUIDName & "|") Then
               $hItem2 = GUICtrlCreateTreeViewItem($GUIDName, $hItem)                                                ;大类
               $IconString = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\" & $GUID, "IconPath")
               If $IconString <> "" Then
                        $tt = StringSplit($IconString, ",")
                        If Not @error And $tt = 2 Then
                           ;If $GUID = "{4d36e968-e325-11ce-bfc1-08002be10318}" Or $GUID = "{eec5ad98-8080-425f-922a-dabf3de3f69a}" Then        ;显卡及便捷设备图标
                                ;$icon = @ScriptDir & "\ICON\" & $GUID & ".ICO"
                                ;$v = 0
                           ;Else
                                  $icon = $tt
                                  $v = $tt
                           ;EndIf
                           _GUICtrlTreeView_SetIcon($DMTree, $hItem2, $icon, $v)
                        EndIf
               EndIf
               $ClassItemString &= $GUIDName & "|"
          EndIf

          $hItem3 = GUICtrlCreateTreeViewItem($Hardware[$a], $hItem2)                        ;硬件添加进 TREE内的大类,如显卡设备属于 显示适配器 类
          _GUICtrlTreeView_SetIcon($DMTree, $hItem3, $icon, $v)
          $hItem4 = GUICtrlCreateTreeViewItem("Version: " & $Hardware[$a], $hItem3)
          _GUICtrlTreeView_SetIcon($DMTree, $hItem4, $icon, $v)
   Next
   GUICtrlSetState($hItem, $GUI_EXPAND)                                                                        ;展开父项
EndFunc

Func _FindDeviceRecur($hDevInst)                                                        ;找到并将符合条件的设备添加进数组,此函数供 _HardwareScan() 函数调用
   $aChild = _CM_Enumerate_Children_Ex($hDevInst, 0)
   For $i = 1 To $aChild
          $hDevInst = _CM_Locate_DevNode($aChild[$i])
          $aChild[$i] = StringUpper($aChild[$i])
          $iStatus = _CM_Get_DevNode_Status($hDevInst)                                                        ;根据设备号来判断设备是否在 设备管理器 内显示出来 $DN_NO_SHOW_IN_DM
          If bitAND($iStatus, $DN_NO_SHOW_IN_DM) Then ContinueLoop

          $CLASSGuid = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_CLASSGUID)                ;根据设备ID取得该设备所属的CLASS
          If $CLASSGuid = "{8ECC055D-047F-11D1-A537-0000F8753ED1}" Then ContinueLoop                ;非即插即用设备 排除

          $DEVName = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_FRIENDLYNAME)                ;设备名称
          If $DEVName = "" Then $DEVName = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_DEVICEDESC)                ;设备名称

          $GetClass = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_CLASS)                ;根据设备ID取得该设备所属的CLASS
          $GetService = _CM_Get_DevNode_Registry_Property($hDevInst, $CM_DRP_SERVICE)
          $tStatus = _CM_Query_Device_Problem($hDevInst)                                                                ;根据设备号返回设备状态代码
          $CLASSName = _SetupDiGetClassDescription($CLASSGuid)


          $Hardware[$HWNum] = _SetupDiGetClassDescription($CLASSGuid)                                ;将设备所属的 Class 中文名称
          $Hardware[$HWNum] = $DEVName                                                                                                ;将设备名称 写进数组
          $Hardware[$HWNum] = _Get_Driver_Version($hDevInst)                                                        ;驱动版本
          $Hardware[$HWNum] = $CLASSGuid                                                                                                ;

          $HWNum += 1
          _FindDeviceRecur($hDevInst)
   Next
EndFunc


Func _Get_Driver_Version($hDevInst)
   $ClassGUID = _CM_Get_DevNode_Registry_Property($hDevInst, 10)
   If $ClassGUID = "" Then Return "Unknown"
   If @OSArch = "X86" Then
          $Reg = "HKLM\SYSTEM\ControlSet001\Control\Class\"
   Else
          $Reg = "HKLM64\SYSTEM\ControlSet001\Control\Class\"
   EndIf

   $Version = RegRead($Reg & $ClassGUID, "DriverVersion")
   If $Version = "" Then
          Return "Unknown"
   Else
          Return $Version
   EndIf
EndFunc

nmgwddj 发表于 2014-9-8 21:17:42

哇个坟,给其他遇到类似问题的人一个解决方法。
楼主代码无需任何更改,第一行增加 #PRE_UseX64=n 已32位方式运行程序即可。

yhxhappy 发表于 2014-9-9 22:11:48

回复 8# nmgwddj


    我都是用AUTOIT官网下载的原版软件,加这个参数能用吗?我一直认为这些参数是汉化版才行的。

nmgwddj 发表于 2014-9-10 09:13:35

回复 9# yhxhappy


    其实就是编译为32位就可以了。

gaoan000 发表于 2016-4-30 16:08:23

回复 1# yhxhappy

您好,我用主楼的代码可以编译运行,为什么下面发的运行提示已重复定义的变量,我在论坛上搜了下,说忽略就可以编译,但是我这过不去,实在不知道为什么了.请问下是您用的是什么版本啊?

yglgogogo 发表于 2019-1-14 22:59:38

来回复求金币来着

adlyx1999 发表于 2019-1-15 04:40:19

来回复求金币来着.h
页: [1]
查看完整版本: [已解决] SetupAPI 在64位系统下获取 设备驱动版本 问题