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.
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 }
Pingback: Automatically Collect Drivers and Build Configuration Manager (Current Branch) Driver Packages with PowerShell | To the Cloud and Back
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.
LikeLike
I am getting a server setup to try and reproduce this error.
LikeLike
Try download the script from Github.
https://gist.github.com/Aeaddy/2eb9b741a5099217440acbdf5f20e56d
I have had some issues w/ copying it from the website. I will still look into the dashes in the host name.
LikeLike