Building Configuration Manager Driver Packages for Windows 7 with PowerShell and Double Driver

Edit 05/23/2016: I have added this script to Github and can be downloaded here.

I just recently posted an article and a PowerShell script that extracts drivers and creates driver packages using Configuration Manager Current Branch here.  One of the things that I particularly liked about that script is that it was written using nothing but native PowerShell cmdlets.  Windows 8.1 introduced to us the Export-WindowsDriver cmdlet.  This cmdlet exports all 3rd-party drivers to a defined location. This cmdlet is not available for use in Windows 7, so the script was only written to work on Windows 8.1, and Windows 10. (The Export-WindowsDriver cmdlet is supported in Server 2012 R2, but I have not tested these scripts on the Server OS.)  I originally had no intentions of building a script to work on Windows 7, but there was an large enough demand for it that I went ahead and put something together.

This leads us to HOW I got this to work.  To work with Windows 7, we needed a 3rd party utility to do the “heavy lifting” of exporting the drivers from our installed Operating System.  There are a few different utilities out there that do “driver scraping”, but I chose Double Driver for this.  Partially because it has been around for a little while now with no issues; but more importantly because of the command line functionality.   Double Driver offers the same functionality that the Export-WindowsDriver cmdlet gives us.

(You can download Double Driver from many locations on the internet.  I take no responsibility for the use of freeware in any environment.  I downloaded it from CNet personally.)

I essentially changed 1 line in the script to use Double Driver.  The examples below will show the old and new entries:

  • Windows 8.1 / Windows 10 script

#Export the drivers to a temp directory
If (Test-Path $NEWLOGFILE){
Write-Output "This script has been cancelled because it has already completed on this device." | out-file $NEWLOGFILE -Append
}Else{
#Changed this line to use Double Driver for Windows 7 support.
Export-WindowsDriver -Destination "$DRIVERPATH\$COMPMODEL-$OSVER-$OSARCH" -Online | out-file $LOGFILE
move-item $LOGFILE $NEWLOGFILE
Remove-Item $DRIVERPATH'\'$COMPMODEL-$OSVER-$OSARCH'\'prn* -Recurse
}

  • Windows 7 script

#Export the drivers to a temp directory
If (Test-Path $NEWLOGFILE){
Write-Output "This script has been cancelled because it has already completed on this device." | out-file $NEWLOGFILE -Append
}Else{
#Changed this line to use Double Driver for WIndows 7 support.
& .\ddc.exe b /target:"$DRIVERPATH\$COMPMODEL-$OSVER-$OSARCH" | out-file $LOGFILE
move-item $LOGFILE $NEWLOGFILE
Remove-Item $DRIVERPATH'\'$COMPMODEL-$OSVER-$OSARCH'\'prn* -Recurse
}

I added the line to run “ddc.exe”, which is the Double Driver command line utility.  I am running this using “.\” indicating it is looking for the  “ddc.exe” utility in its current running directory.  I do this because I am running these scripts Configuration Manager task sequences.  Granted there is nothing stopping anyone from running them manually, that is how they were initially tested, I want them to run from CfgMgr.  So I built a Package that contains the PowerShell script, only this time I include the Double Driver utility in the package source location.

win7driverscript

I create the CfgMGr package with no Program. Then I create a Task Sequence to run the PowerShell script.  (I describe why I use this method in the previous article found here.)

So with 1 line change, and the addition of a small utility, I can now automate a driver export from a client, import into CfgMGr, and build a driver package with one PowerShell script.

Below is a screenshot of the Task Sequence I use.  It has both the Windows 8.1/10 and Windows 7 script and use the “Operating System Version” check in the Task Sequence Options.

 

#This script will run on any Windows 7 device and extract the drivers into a temp directory. It will then copy those drivers to a share provided in the parameter $SHARENAME.
#Next the script will connect to the primary site server provided in the $CMSITESERVER parameter and initiate the driver import and package build process.
#PSremote must be enabled on the Primary Site server and you must be running the latest version of the PowerShell cmdlets.
#This script must be run w/ an account that has access to the Primary Site Server and the file shares that are being used.
#The $CMDPSiteServer parameter is distribution points for distributing the driver package. This excepts multiple distribution points seperated by commas.
#The $PKGSHARENAME is the share location that the driver package will be stored.

[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[string]$CMSiteServer,

[Parameter(Mandatory=$True, Position=1)]
[string[]]$CMDPSiteServer,

[Parameter(Mandatory=$True, Position=2)]
[string]$SHARENAME,

[Parameter(Mandatory=$True, Position=3)]
[string]$PKGSHARENAME
)

#Do not change these!
$COMPMODEL=(Get-WmiObject -Class win32_computersystem).Model
$OSVER=(Get-WmiObject -Class win32_operatingsystem).Caption
$OSARCH=(Get-WmiObject -Class win32_operatingsystem).OSArchitecture
$UTEMP=$env:TEMP
$DRIVERPATH ="$UTEMP\Drivers"
$LOGFILE ="$UTEMP\$COMPMODEL.log"
$NEWLOGFILE ="$UTEMP\Drivers\$COMPMODEL-$OSVER-$OSARCH.log"
$DriverPackageName = "$COMPMODEL-$OSVER-$OSARCH"
$DriverPackageSource="$PKGSHARENAME\$COMPMODEL-$OSVER-$OSARCH"
$DriverSource="$SHARENAME\$COMPMODEL-$OSVER-$OSARCH"
$DriverCategoryName01 = $OSVER
$DriverCategoryName02 = $COMPMODEL

$ScriptBlock = { param($SDriverPackageName, $SDriverPackageSource, $SDriverPackage, $SCMDPSiteServer, $SDriverCategoryName01, $SDriverCategoryName02, $SDrivers, $SDriverSource)

$snip = $env:SMS_ADMIN_UI_PATH.Length-5
$modPath = $env:SMS_ADMIN_UI_PATH.Substring(0,$snip)
Import-Module "$modPath\ConfigurationManager.psd1"
$SiteCode = Get-PSDrive -PSProvider CMSite

#Create Driver Package
Set-Location "$($SiteCode.Name):\"
New-CMDriverPackage -Name $SDriverPackageName -Path $SDriverPackageSource -Verbose
$SDriverPackage = Get-CMDriverPackage -Name $SDriverPackageName
Start-CMContentDistribution -DriverPackageName $SDriverPackage.Name -DistributionPointName $SCMDPSiteServer -Verbose

#Create Administrative Categories
If ((Get-CMCategory -Name $SDriverCategoryName01) -eq $null) {New-CMCategory -CategoryType DriverCategories -Name $SDriverCategoryName01 }
$SDriverCategory01 = Get-CMCategory -Name $SDriverCategoryName01
If ((Get-CMCategory -Name $SDriverCategoryName02) -eq $null) {New-CMCategory -CategoryType DriverCategories -Name $SDriverCategoryName02 }
$SDriverCategory02 = Get-CMCategory -Name $SDriverCategoryName02

#Build Category array
$SDriverCategories = @()
$SDriverCategories += $SDriverCategory01
$SDriverCategories += $SDriverCategory02

#Get Drivers
Set-Location C:
$SDrivers = Get-ChildItem -Path $SDriverSource -Include *.inf -Recurse
Set-Location "$($SiteCode.Name):\"

#Import Drivers
foreach ($SDriver in $SDrivers) {Import-CMDriver -UncFileLocation $SDriver.FullName -DriverPackage $SDriverPackage -EnableAndAllowInstall $true -AdministrativeCategory $SDriverCategories -ImportDuplicateDriverOption AppendCategory -ErrorAction SilentlyContinue -Verbose }

}

#End of declarations
If (Test-Path $DriverPackageSource){
exit 0
}ELSE{

#Export the drivers to a temp directory
If (Test-Path $NEWLOGFILE){
Write-Output "This script has been cancelled because it has already completed on this device." | out-file $NEWLOGFILE -Append
}Else{
#Changed this line to use Double Driver for Windows 7 support.
& .\ddc.exe b /target:"$DRIVERPATH\$COMPMODEL-$OSVER-$OSARCH" | out-file $LOGFILE
move-item $LOGFILE $NEWLOGFILE
Remove-Item $DRIVERPATH'\'$COMPMODEL-$OSVER-$OSARCH'\'prn* -Recurse
}

#Copy Drivers to Driver Repository
If (Test-Path $SHARENAME'\'$COMPMODEL){
Write-Output "This Copy has been cancelled because it has already completed for this device." | out-file $NEWLOGFILE -Append
}Else{
copy-item $DRIVERPATH'\*' -Destination $SHARENAME -Recurse
}

#Connect to CM Primary Site Server
$CMSESSION=New-PSSession -ComputerName $CMSiteServer

#Execute commands on remote server
invoke-command -Session $CMSESSION `
-ScriptBlock $Scriptblock `
-Args $DriverPackageName, $DriverPackageSource, $DriverPackage, $CMDPSiteServer,$DriverCategoryName01, $DriverCategoryName02, $Drivers, $DriverSource

#Cleanup Temp directory
Remove-Item "$UTEMP\Drivers"-Recurse
}

4 thoughts on “Building Configuration Manager Driver Packages for Windows 7 with PowerShell and Double Driver

  1. Pingback: Automatically Collect Drivers and Build Configuration Manager (Current Branch) Driver Packages with PowerShell | To the Cloud and Back

  2. I am trying to run this powershell script and I believe it isn’t liking that we have hyphens “-” in our server names. I am not much of a powershell person, but I wanted to ask if this script will run with hyphens in server names just to verify whether or not I am wrong.

    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