Get devices info from the registry

I’ve been using devcon.exe for years. For those who don’t know what is this handy utility, it’s actually the ‘Device Manager’ command line equivalent. It can update drivers, list all devices, list their status, enable or disable devices… . In other words, this executable happens to be very resourceful. It can be found in the Windows Driver Kit as well as its source code. We have been using it for example to get hardware IDs of the new drivers’ set when we integrate a new mainboard model into our environment. However it has a drawback when you look for the hardware ID of the network card, you have to know that the Class of the netword card is ‘Net’ so that you do ‘devcon.exe findall =Net’ to limit the console output. So to get around this limitation, I ended writing a powershell script that will give the same console output as ‘devcon.exe findall *’, with the Class as third column and return it as an object. Note that the devcon.exe utility doesn’t read the registry but uses the SetupAPI to achieve all its tasks.

#Requires -Version 2.0

<#
 
.SYNOPSIS    
    Read devices information from the registry
 
.DESCRIPTION  
    Read devices information from the registry

.PARAMETER Findall
    Get all devices

.PARAMETER Find
    Specifies a string to look for

.EXAMPLE    
    Get-Devcon.ps1 -Findall

    Returns all devices information like devcon.exe findall *
    You'll get 3 properties, Hardware ID (HwID), the Class and the FriendlyName as well as the total count.

.EXAMPLE    
    Get-Devcon.ps1 -Find =Net
    Retrieve all devices from the Net class like devcon.exe find =Net
 
.EXAMPLE    
    .\Get-Devcon.ps1 -Find "ACPI\PNP0C0D\2&daba3ff&2"

Manufacturer      : Microsoft
DriverDescription : ACPI Lid
DriverDate        : 6/21/2006 12:00:00 AM
InfFilePath       : C:\Windows\inf\machine.inf
DriverVersion     : 6.1.7601.17514
InfSection        : NO_DRV

    Returns some information about a specific hardware ID.

.EXAMPLE    
    .\Get-Devcon.ps1 -Find *PNP*

    Retrieve all devices where their hardware ID matches the string with wildcards *PNP*

.NOTES    
    Name: Get-Devcon
    Author: Emin Atac
    DateCreated: 03/03/2012
 
.LINK    
    https://p0w3rsh3ll.wordpress.com
 
#>

[CmdletBinding(DefaultParameterSetName='Findall', SupportsTransactions=$false)]
param(
   [Parameter(ParameterSetName='Findall', Mandatory=$false, Position=0)]
    [System.Management.Automation.SwitchParameter]${Findall},

    [Parameter(ParameterSetName='Find', Mandatory=$true, Position=0)]
    [system.string]${Find}
)


$root = Get-Childitem "HKLM:\SYSTEM\CurrentControlSet\Enum"
$classroot = Get-item "HKLM:\SYSTEM\CurrentControlSet\Control\Class"
$alldevices = @()
foreach ($i in $root)
{
    $Class = $i.PSChildName

    # Build the subkey path    
    $subkeylevel1 = Join-Path -Path $i.PSParentPath -ChildPath $i.PSChildName

    # Get its properties
    $subkeyslevel2 = Get-Childitem -Path $subkeylevel1

    foreach ($j in $subkeyslevel2)
    {
        $subkeylevel3 = Join-Path -Path $j.PSParentPath -ChildPath $j.PSChildName
        $HardwareID = $j.PSChildName
        $subkeyslevel4 = Get-Childitem -LiteralPath $subkeylevel3
        foreach ($k in $subkeyslevel4)
        {
            $properties = $FriendlyName = $desc = $null
            $properties = Get-ItemProperty $k.PSPath
            if ($properties.FriendlyName -eq $null)
            {
                if ($properties.DeviceDesc -match "^@")
                {
                    $FriendlyName = ($properties.DeviceDesc -split ";")[1]
                    if ($FriendlyName -eq $null)
                    {
                        $FriendlyName = ($properties.DeviceDesc -split ";")[0]
                        switch($FriendlyName)
                        {
                            "@%systemroot%\system32\drivers\afd.sys,-1000"     { $desc = "Ancillary Function Driver for Winsock" }
                            "@%systemroot%\system32\appidsvc.dll,-102"         { $desc = "AppID Driver" }
                            "@%systemroot%\system32\browser.dll,-102"          { $desc = "Browser Support Driver" }
                            "@%SystemRoot%\system32\clfs.sys,-100"             { $desc = "Common Log (CLFS)" }
                            "@%systemroot%\system32\cscsvc.dll,-202"           { $desc = "Offline Files Driver" }
                            "@%systemroot%\system32\drivers\dfsc.sys,-101"     { $desc = "DFS Namespace Client Driver" }
                            "@%systemroot%\system32\drivers\discache.sys,-102" { $desc = "System Attribute Cache" }
                            "@%SystemRoot%\system32\drivers\fileinfo.sys,-100" { $desc = "File Information FS MiniFilter" }
                            "@%SystemRoot%\system32\drivers\fltmgr.sys,-10001" { $desc = "FltMgr" }
                            "@%SystemRoot%\system32\drivers\fvevol.sys,-100"   { $desc = "Bitlocker Drive Encryption Filter Driver" }
                            "@%SystemRoot%\system32\drivers\http.sys,-1"       { $desc = "HTTP" }
                            "@%systemroot%\system32\drivers\hwpolicy.sys,-101" { $desc = "Hardware Policy Driver" }
                            "@%systemroot%\system32\drivers\luafv.sys,-100"    { $desc = "UAC File Virtualization" }
                            "@%SystemRoot%\system32\drivers\mountmgr.sys,-100" { $desc = "Mount Point Manager" }
                            "@%SystemRoot%\system32\FirewallAPI.dll,-23092"    { $desc = "Windows Firewall Authorization Driver" }
                            "@%systemroot%\system32\webclnt.dll,-104"          { $desc = "WebDav Client Redirector Driver" }
                            "@%systemroot%\system32\wkssvc.dll,-1002"          { $desc = "SMB MiniRedirector Wrapper and Engine" }
                            "@%systemroot%\system32\wkssvc.dll,-1004"          { $desc = "SMB 1.x MiniRedirector" }
                            "@%systemroot%\system32\wkssvc.dll,-1006"          { $desc = "SMB 2.0 MiniRedirector" }
                            "@%systemroot%\system32\drivers\mup.sys,-101"      { $desc = "MUP" }
                            "@%SystemRoot%\system32\drivers\ndis.sys,-200"     { $desc = "NDIS System Driver" }
                            "@%SystemRoot%\system32\drivers\netbt.sys,-2"      { $desc = "NETBT" }
                            "@%SystemRoot%\system32\drivers\nsiproxy.sys,-2"   { $desc = "NSI proxy service driver." }
                            "@%SystemRoot%\System32\drivers\pacer.sys,-101"    { $desc = "QoS Packet Scheduler" }
                            "@%systemroot%\system32\wkssvc.dll,-1000"          { $desc = "Redirected Buffering Sub Sysytem" }
                            "@%systemroot%\system32\DRIVERS\RDPCDD.sys,-100"   { $desc = "RDPCDD" }
                            "@%systemroot%\system32\drivers\RDPENCDD.sys,-101" { $desc = "RDP Encoder Mirror Driver" }
                            "@%systemroot%\system32\drivers\RdpRefMp.sys,-101" { $desc = "Reflector Display Driver used to gain access to graphics data" }
                            "@%systemroot%\system32\srvsvc.dll,-102"           { $desc = "Server SMB 1.xxx Driver" }
                            "@%systemroot%\system32\srvsvc.dll,-104"           { $desc = "Server SMB 2.xxx Driver" }
                            "@%SystemRoot%\system32\vmstorfltres.dll,-1000"    { $desc = "Disk Virtual Machine Bus Acceleration Filter Driver" }
                            "@%SystemRoot%\system32\tcpipcfg.dll,-50003"       { $desc = "TCP/IP Protocol Driver" }
                            "@%SystemRoot%\system32\tcpipcfg.dll,-50004"       { $desc = "NetIO Legacy TDI Support Driver" }
                            "@%SystemRoot%\System32\DRIVERS\tssecsrv.sys,-101" { $desc = "Remote Desktop Services Security Filter Driver" }
                            "@%SystemRoot%\system32\drivers\volmgrx.sys,-100"  { $desc = "Dynamic Volume Manager" }
                            "@%systemroot%\system32\rascfg.dll,-32012"         { $desc = "Remote Access IPv6 ARP Driver" }
                            default                                            { $desc = ""}
                        }
                        $FriendlyName  = $desc
                    }

                } else {
                    $FriendlyName = $properties.DeviceDesc
                }
            } else {
                if ($properties.FriendlyName -match "^@")
                {
                    $FriendlyName = ($properties.FriendlyName -split ";")[1]
                } else {
                    $FriendlyName = $properties.FriendlyName
                }
            }
            
            $Object = $null
            # Build an object to store all the properties we are interested in
            $Object = New-Object -TypeName PSObject -Property @{
                HwID = $Class + "\" + $HardwareID + "\" + $k.PSChildName
                FriendlyName = $FriendlyName
                Class = $properties.Class
                Driver = $properties.Driver
                CompatibleIDs = $properties.CompatibleIDs
            }
            # Now that we have a link to its driver info, we can gather additional info from the registry
            if ($properties.Driver -ne $null)
            {
                $driverinfopath = Join-Path -Path $classroot.PSPath -ChildPath $properties.Driver
                if (Test-Path $driverinfopath)
                {
                    $driverproperties = Get-ItemProperty -Path $driverinfopath

                    $DriverProperties = New-Object -TypeName PSObject -Property @{            
                        InfFilePath = "$env:systemroot\inf\" + $driverproperties.InfPath
                        InfSection = $driverproperties.InfSection
                        DriverDescription = $driverproperties.DriverDesc
                        Manufacturer = $driverproperties.ProviderName
                        DriverDate = [datetime]$driverproperties.DriverDate
                        DriverVersion = [version]$driverproperties.DriverVersion
                    }
                    $Object | add-member Noteproperty -Name DriverProperties -Value $DriverProperties

                }
            }
            # Add the object to our array    
            $alldevices += $Object
        } # end of foreach level 4
    } # end of foreach level 2
    # break
} # end of foreach root

# Main
switch ($PsCmdlet.ParameterSetName)
{ 
    Findall {
        $alldevices | Select-Object -Property HWID,Class,FriendlyName
        Write-Host -ForegroundColor Gray -Object ("$($alldevices.count) matching device(s) found.")
    }
    Find {
        if ($Find -match "^=")
        {
            $Find  = $Find -replace "=",""
            $results = $alldevices | Where-Object { $_.Class -eq $Find}
            $results | Select-Object -Property HWID,Class,FriendlyName
            Write-Host -ForegroundColor Gray -Object ("$($results.count) matching device(s) found.")
        } elseif ($Find -match "^\*$" ) {
            $results = $alldevices | Where-Object { $_.HwID -match "."}
            $results | Select-Object -Property HWID,Class,FriendlyName
            Write-Host -ForegroundColor Gray -Object ("$($results.count) matching device(s) found.")
        } elseif ($Find -match "^\*.+\*$" ) {
            $Find = $Find -replace "\*",".+"
            $results = @()
            $results += $alldevices | Where-Object { $_.HwID -match $Find}
            $results += $alldevices | Where-Object { $_.FriendlyName -match $Find}
            $results += $alldevices | Where-Object { $_.CompatibleIDs -match $Find}
            $results | Sort-Object -Unique -Property HWID | Select-Object -Property HWID,Class,FriendlyName
            Write-Host -ForegroundColor Gray -Object ("$(($results | Sort-Object -Unique -Property HWID).count) matching device(s) found.")
        } elseif ($Find -match "^[a-z]+\\.+" ) {
            $alldevices | Where-Object { $_.HwID -match [regex]::escape($Find) } | Select-Object -Property DriverProperties -ExpandProperty DriverProperties
        } else {

        }
    }
} # end of switch

With the above script we can now get the list of all classes names as well as how many devices they hold:
devcon example 2

Advertisements

2 thoughts on “Get devices info from the registry

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s