2

Using DevCon utility, I ran this command to get the list of all of the drivers installed in the computer.

devcon.exe driverfiles * > drivers.txt

The output looks like this:

USB\ROOT_HUB20\4&361B340A&0
    Name: USB Root Hub
    Driver installed from C:\windows\INF\usbport.inf [ROOTHUB.Dev]. 2 file(s) used by driver:
        C:\windows\system32\drivers\usbhub.sys
        C:\windows\system32\drivers\usbd.sys
ACPI\PNP0C09\1
USB\ROOT_HUB20\4&361B340A&1
    Name: USB Root Hub
    Driver installed from C:\windows\INF\usbport.inf [ROOTHUB.Dev]. 2 file(s) used by driver:
        C:\windows\system32\drivers\usbhub.sys
        C:\windows\system32\drivers\usbd.sys

I then used PowerShell script to parse the file. Thanks to TheMadTechnician.

(Get-Content C:\Path\To\File.txt) -join "`r`n" -Split "(?m)^(?=\S)" |
    Where{$_} | 
    ForEach{
        Clear-Variable Files,Driver,Name,HardwareID
        $Files = @()
        $HardwareID = ($_ -split "`r`n")[0].trim()
        Switch -regex ($_ -split "`r`n"){
            "^\s+Name:" {$Name = ($_ -split ':',2)[-1].trim();Continue}
            "^\s+.:\\" {$Files += $_.trim();continue}
            "^\s+Driver" {$Driver = [RegEx]::Matches($_,"(?<=Driver installed from )(.+?)(?= \[)").value;continue}
        }
        [PSCustomObject]@{'HardwareID' = $HardwareID;'Name' = $Name; 'Files' = $Driver; 'FileVersion' = If(Test-Path $_.Trim()){[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.trim()).FileVersion}}
    $Files | ForEach{ [PSCustomObject]@{'HardwareID' = $HardwareID;'Name' = $Name; 'Files' = $_; 'FileVersion' = If(Test-Path $_.Trim()){[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.trim()).FileVersion}Else{'File Not Found'}}}

Now, the output after running the script is:

HardwareID                  Name                                            Files                                  FileVersion                             
----------                  ----                                            -----                                  -----------                             
USB\ROOT_HUB20\4&361B340A&0 USB Root Hub                                    C:\windows\INF\usbport.inf                                                     
USB\ROOT_HUB20\4&361B340A&0 USB Root Hub                                    C:\windows\system32\drivers\usbhub.sys 6.3.9600.17238 (winblue_gdr.140723-2018)
USB\ROOT_HUB20\4&361B340A&0 USB Root Hub                                    C:\windows\system32\drivers\usbd.sys   6.3.9600.17195 (winblue_gdr.140530-1506)
ACPI\PNP0C09\1                                                                                                                                             
USB\ROOT_HUB20\4&361B340A&1 USB Root Hub                                    C:\windows\INF\usbport.inf                                                     
USB\ROOT_HUB20\4&361B340A&1 USB Root Hub                                    C:\windows\system32\drivers\usbhub.sys 6.3.9600.17238 (winblue_gdr.140723-2018)
USB\ROOT_HUB20\4&361B340A&1 USB Root Hub                                    C:\windows\system32\drivers\usbd.sys   6.3.9600.17195 (winblue_gdr.140530-1506)

THE PROBLEM

I would like to add an extra column with driver version.

How can I find the driver version and list it next to the name column? Thank you!

EDIT

The code below parses driver version from the INF file. I am not experienced with PowerShell, so how can I used this bit of information and incorporate it with the above code to add an extra column and list driver version; preferably, next to Name column.

$pattern = 'DriverVer\s*=\s*(?:\d+/\d+/\d+,)?(.*)'
Select-String -Pattern $pattern -Path $path |
  select -Expand Matches -First 1 |
  % { $_.Groups[1].Value }

# $path = the INF file
6
  • Is your question how to get the driver version out of devcon? Or how to adding the column to your PS output? The latter is simply adding it to the [PSCustomObject] line in your script. Commented Jul 1, 2015 at 20:25
  • The goal is to list driver version in a column. I can use devcon.exe drivernodes to list the version. But that would be a second command; hence, separate file(not sure if I can use and out in DevCon). Is there way to user PS command during parsing to find the version? [PSCustomObject] what param would give the driver version? Commented Jul 1, 2015 at 20:30
  • That's not actually the code that will result in that output (go back and look at my answer again, you need to replace that [PSCustomObject] line). But rather than just feeding you the answer this time, I'll give you what you need to do this yourself with a little effort. Look into Select-String, and the Line property that it outputs. Then use the[RegEx]::Matches method I used above with "(?<=,)(.*)$" as your match string. Come back with an error if you try and fail. Commented Jul 2, 2015 at 0:09
  • I had forgotten about this... if you're running Windows 8 you can just use Get-WindowsDriver instead of having to parse through the inf file. Commented Jul 2, 2015 at 1:52
  • @TheMadTechnician with some help, I am able to get this: '$pattern = 'DriverVer\s*=\s*(?:\d+/\d+/\d+,)?(.*)' Select-String -Pattern $pattern -Path $path | select -Expand Matches -First 1 | % { $_.Groups[1].Value }' - Since, I am new to PowerShell, not quite sure how I can make this to object so [PSCustomObject] can be tweaked to print it out in the column. Commented Jul 6, 2015 at 23:22

1 Answer 1

1

Adding a new column is relatively simple. The columns are listed because they are properties of the object in the array. So right now we have object that are built like this (the driver line is similar, and then we pipe all remaining files into this, line breaks added for ease of reading):

[PSCustomObject]@{
    'HardwareID' = $HardwareID
    'Name' = $Name
    'Files' = $_
    'FileVersion' = If(Test-Path $_.Trim()){[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.trim()).FileVersion}Else{'File Not Found'}
}

From that we get the four columns 'HardwareID, 'Name', 'Files', and 'FileVersion'. If you want to add a column you can simply insert another property. In this case you want to add a new column next to Name that has the version of the driver for each item. We can simply re-purpose the line that currently outputs the driver file path (with missing version number) for each item:

[PSCustomObject]@{'HardwareID' = $HardwareID;'Name' = $Name; 'Files' = $Driver; 'FileVersion' = If(Test-Path $_.Trim()){[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.trim()).FileVersion}}

With that line we can just remove the bit in there that tries to list anything in the 'FileVersion' column, and add a new one in there for 'DriverVersion' using the code that you supplied (with some minor modifications). We're going to move the $Pattern = line to be the first line of the script, since we don't need to re-assign that for each iteration of the loop. Then we are going to assign the rest of your code to the new 'DriverVersion' property/column, and wrap it in a If($Driver){} statement, so that it doesn't throw errors for entries that don't have a driver listed. So that now looks like this:

        [PSCustomObject]@{
            'HardwareID' = $HardwareID
            'Name' = $Name
            'DriverVersion' = If($Driver){Select-String -Pattern $pattern -Path $driver | select -Expand Matches -First 1 |%{ $_.Groups[1].Value }}else{''}
            'Files' = $Driver
            'FileVersion' = '' }

Now, since we added that property to that line, we need to update the next line as well so that it includes that property as well (albeit with a blank value):

        $Files | ForEach{ [PSCustomObject]@{'HardwareID' = $HardwareID;'Name' = $Name; 'DriverVersion'= ''; 'Files' = $_; 'FileVersion' = If(Test-Path $_.Trim()){[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.trim()).FileVersion}Else{'File Not Found'}}}

The updated code as a whole would look something like:

$pattern = 'DriverVer\s*=\s*(?:\d+/\d+/\d+,)?(.*)'
(Get-Content C:\Path\To\File.txt) -join "`r`n" -Split "(?m)^(?=\S)" |
    Where{$_} | 
    ForEach{
        Clear-Variable Files,Driver,Name,HardwareID,DriverVer -ea SilentlyContinue
        $Files = @()
        $HardwareID = ($_ -split "`r`n")[0].trim()
        Switch -regex ($_ -split "`r`n"){
            "^\s+Name:" {$Name = ($_ -split ':',2)[-1].trim();Continue}
            "^\s+.:\\" {$Files += $_.trim();continue}
            "^\s+Driver" {$Driver = [RegEx]::Matches($_,"(?<=Driver installed from )(.+?)(?= \[)").value;continue}
        }

        [PSCustomObject]@{
            'HardwareID' = $HardwareID
            'Name' = $Name
            'DriverVersion' = If($Driver){Select-String -Pattern $pattern -Path $driver | select -Expand Matches -First 1 |%{ $_.Groups[1].Value }}else{''}
            'Files' = $Driver
            'FileVersion' = '' }
        $Files | ForEach{ [PSCustomObject]@{'HardwareID' = $HardwareID;'Name' = $Name; 'DriverVersion'= ''; 'Files' = $_; 'FileVersion' = If(Test-Path $_.Trim()){[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.trim()).FileVersion}Else{'File Not Found'}}}
    }|ft

This now outputs something along the lines of:

HardwareID                  Name                                            DriverVersion  Files                                  FileVersion                             
----------                  ----                                            -------------  -----                                  -----------                             
USB\ROOT_HUB20\4&361B340A&0 USB Root Hub                                    6.3.9600.17238 C:\windows\INF\usbport.inf                                                     
USB\ROOT_HUB20\4&361B340A&0 USB Root Hub                                                   C:\windows\system32\drivers\usbhub.sys 6.3.9600.17238 (winblue_gdr.140723-2018)
USB\ROOT_HUB20\4&361B340A&0 USB Root Hub                                                   C:\windows\system32\drivers\usbd.sys   6.3.9600.17195 (winblue_gdr.140530-1506)
ACPI\PNP0C09\1                                                                                                                                                            
USB\ROOT_HUB20\4&361B340A&1 USB Root Hub                                    6.3.9600.17238 C:\windows\INF\usbport.inf                                                     
USB\ROOT_HUB20\4&361B340A&1 USB Root Hub                                                   C:\windows\system32\drivers\usbhub.sys 6.3.9600.17238 (winblue_gdr.140723-2018)
USB\ROOT_HUB20\4&361B340A&1 USB Root Hub                                                   C:\windows\system32\drivers\usbd.sys   6.3.9600.17195 (winblue_gdr.140530-1506)
ACPI\PNP0C09\2                                                                                                                                                            
USB\ROOT_HUB20\4&361B340A&2                                                 6.3.9600.16384 C:\windows\INF\cmbatt.inf                                                      
USB\ROOT_HUB20\4&361B340A&2                                                                C:\windows\system32\DRIVERS\CmBatt.sys 6.3.9600.16384 (winblue_rtm.130821-1623)
USB\ROOT_HUB20\4&361B340A&2                                                                C:\windows\system32\DRIVERS\battc.sys  6.3.9600.16384 (winblue_rtm.130821-1623)
ACPI\PNP0C0A\2              Microsoft ACPI-Compliant Control Method Battery 6.3.9600.16384 C:\windows\INF\cmbatt.inf                                                      
ACPI\PNP0C0A\2              Microsoft ACPI-Compliant Control Method Battery                C:\windows\system32\DRIVERS\CmBatt.sys 6.3.9600.16384 (winblue_rtm.130821-1623)
ACPI\PNP0C0A\2              Microsoft ACPI-Compliant Control Method Battery                C:\windows\system32\DRIVERS\battc.sys  6.3.9600.16384 (winblue_rtm.130821-1623)
Sign up to request clarification or add additional context in comments.

1 Comment

I tried to export that data to a CSV file and ran into a problem. May be you can guide me in the right direction. PowerShell Export-CSV is not Working

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.