Driver Updates using powershell

At a recent visit to a customer the mentioned they have an issue with a network driver on some laptops and desktops. So read on for a way to sort that out with the help of powershell and some commandline tools.

The issue

In a some specific network cards from Intel in certain Lenovo laptops and desktop there is an issue causing random CPU spikes in the network switches. The fix in it self is to upgrade to the latest driver. Seems easy enough.

Looking for a solution

So off to Lenovo’s support page for the latest driver, install on a test machine and watch the magic. Well almost, the problem is still there. But hey there is a newer driver from Intel. Off to Intels homepage and download the newer driver. Install and watch the magic! Well almost again. The driver doesn’t get used since PnP matching in Win7 and Win8 ranks the older Lenovo driver as a better driver.

Easy fix, eject the driver and reinstall the card with a new driver! Done, works like a charm!

The fix

Only one problem to go then. How do we automate this on 200 machines? There are two parts to this. First off the hard part. We need to eject the driver from the machine and the solution must work on Win7 and Win8. PnPUtil.exe is your friend, just use pnputil.exe -f -d <driver.inf> and your done. So how do we know what driver.inf to input since all machines use third party drivers they are all named oemxxx.inf with a random number. So we need to get the inf file name. To do this we download DevCon.exe from the Windows Driver Kit (found here). We then use PowerShell to get the network device using wmi and combine that with devcon to get the inf used for that device.

Then it is a small matter of eject the driver and installing a new one from a given path.

The Script

The script uses a few parameters the first and the only mandatory one is -search. This is used to make sure we only find the device we need. The script will search for network devices with the search parameter in its name. If it finds two or more it will break out to make sure we don’t break any devices and it will also break out if it doesn’t find any device at all.

Next we have the -ReplacePath parameter which needs to be pointed to the path to new inf file. It can be either a directory or a specific inf file. For examples to this do get-help update-driver.ps1.

There is also an -delete switch if for some reason you just want to delete the driver.

The script has been tested standalone as a ConfigMgr package. If you want to run this as a ConfigMgr package please make sure to use the full powershell.exe commandline. E.g. powershell.exe –executionpolicy Bypass –file Update-Driver.ps1 –search Ethernet –ReplacePath .\Network\*.inf

In the folder where the script is places create two new folders, one named x64 and one named x86 and in each one place the respective architecture devcon.exe tool.

Download Script

<#
Created:   2015-02-16
Version:    1.0
Author :    Peter Lofgren
Twitter:    @LofgrenPeter
Blog     :     https://syscenramblings.wordpress.com
Disclaimer:
This script is provided “AS IS” with no warranties, confers no rights and
is not supported by the author
#>
<#
.Synopsis
Search, Remove and Repalce Inffiles
.DESCRIPTION
Search for a network device and delete or replace the inf used by the device.
.EXAMPLE
Update-Driver.ps1 -search Ethernet -ReplacePath C:\Drivers\Network\Driver.inf
.EXAMPLE
Update-Driver.ps1 -search Ethernet -ReplacePath C:\Drivers\Network\*.inf
#>
Param(
[Parameter(Mandatory=$true)]
$Search,
[Parameter()]
$ReplacePath,
[Parameter()]
[Switch]$Delete
)

#Get current wokring paths
$CurrentDirectory = split-path $MyInvocation.MyCommand.Path
$ScriptName = $MyInvocation.MyCommand.Name

#Verify OS
If ([environment]::Is64BitOperatingSystem -eq $True) {
$DevCon = “x64\devcon.exe”
$PNPUtil = “C:\Windows\sysnative\pnputil.exe”
}
Else {
$DevCon = “x86\devcon.exe”
$PnPUtil = “C:\Windows\System32\pnputil.exe”
}
Write-Host “Current Path: $CurrentDirectory”
Write-Host “Current Scriptname: $ScriptName”
#Verify DevCon exsits
If (!(Test-path “$CurrentDirectory\$DevCon”)) {
Write-Warning “Missing $DevCon, cannot continue”
Exit $LASTEXITCODE
}
#Get inf Name
$Adapter = Get-WmiObject -Class win32_networkadapter | where { $_.name -like “*$Search*” }
If (!$Adapter) {
Write-Warning “No Adapter found matching searchcriteria”
  Exit “666”
}
ElseIf ($Adapter.Count -ge “1”) {
Write-Warning “More than one adapter found cannot continue”
Exit “666”
}
$AdapterName = $Adapter.Name
$PnpID = $Adapter.PNPDeviceID -replace(“&”,”*”)
$PnpID = $PnpID.Substring(0,40) + “*”
$DriverFiles = cmd /c  “$CurrentDirectory\$DevCon driverfiles $PnpID”
$Path = Select-String -InputObject $DriverFiles -Pattern ‘.inf’
$InfName = (($Path.Line) -replace (“.*Driver installed from “,””)) -replace(“.inf .*”,”.inf”)
$InfName = $InfName.Split(“\”)
$InfName = $InfName[$($InfName.Count – 1)]
Write-Host “”
Write-Host “AdapterName: $AdapterName”
If (!$InfName) {
Write-Host “No inf specified”
}
Else {
Write-host “Inf FileName: $InfName”
}
IF ($Delete) {
cmd/c “$PnPUtil -f -d $InfName”
}
If ($ReplacePath) {
If ((Test-Path $ReplacePath)) {
cmd /c “$PnPUtil -f -d $InfName”
cmd /c “$PnPUtil -i -a $ReplacePath”
}
Else {
Write-Warning “Path $ReplacePath not Found!”
Exit “666”
}
}
Advertisements

2 comments

  1. Hey,

    Great work by the way.
    I’m just doing a bit of research into updating network drivers using powershell and your script might just be most of what I’m looking for. Sadly, the one-drive link appears to be dead. If you know where else I might be able to find it that would be fantastic.

    Thanks,
    Rich

    Like

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