Automatically Collect Drivers and Build Configuration Manager (Current Branch) Driver Packages with PowerShell

EDIT 05/17/2016: I have added a link to the script on GitHub.

EDIT 05/15/2016: I have added a link to the Win7 version that uses Double Driver.

EDIT 04/26/2016: I have added a condition to check to see if the driver package path exists, and if it does, to exit and not rerun.

EDIT 04/18/2016: I have updated the script to create the driver package and driver package directories, and said logs, to include the OS and architecture.  This way we can dump any device into a collection regardless of the OS and architecture, and we do not have to worry about getting the drivers stored in the proper locations. (E.g.: Surface Pro 3-Microsoft Windows 10 Pro-64-bit)

As we all know downloading and organizing drivers has always been a tedious task.  This script will help with both the initial setup of Configuration Manager in your environment, or it can be used for acquiring the drivers for new hardware models being introduced into the environment.  As we look to grow and mature our environment, we need to find ways to automate these mundane tasks; and I hope this Power Shell script can help to do that.

So what does this script do?  This script can be run on any Windows 8.1 or Windows 10 workstation that has the latest version of PowerShell.  This script will export all of the drivers from a device and will store them in a temp location on the device. It will copy those drivers into a share that is provided.

Next the script will connect to the Primary Site server and will create a driver package with the name of the computer model (Ex. “Surface Pro 3”) and it will distribute it to the distribution points that are provided in the parameters.  Next it creates Categories for the drivers that match the model name, and the OS version.  Then it will import the drivers into Configuration Manager and it will add them to the driver package.  Finally it will delete the files in the local temp location.

The script posted below does have a few requirements.  Those requirements are are as follows:

  1. This script was built and tested on the lastest version of Configuration Manager Current Branch and requires the most up to date powershell cmdlets.
  2. PowerShell remoting(WinRM) must be enabled on the Primary Site Server.
  3. The script must be run by an account that has the proper access to the Primary Site Server, and the driver source share that the drivers get copied into from the client device.
#This script will run on any Windows 8 or Windows 10 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.

CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[string]$CMSiteServer,
[Parameter(Mandatory=$True, Position=1)]
[string[]]$CMDPSiteServer,</div>
[Parameter(Mandatory=$True, Position=2)]
[string]$SHARENAME,</div>
[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{
Export-WindowsDriver -Destination "$DRIVERPATH\$COMPMODEL-$OSVER-$OSARCH" -Online | out-file $LOGFILE
move-item $LOGFILE $NEWLOGFILE
Remove-Item $DRIVERPATH'\'$COMPMODEL'\'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
}

 

Next let’s talk about how we can use this script in an existing Configuration Manager environment.  We COULD just find a machine and run the script on it manually and that would work just fine.  We could even use Power Shell remoting to connect to our devices and run the script; but that still seems a little bit to manual for me.  I am a Systems efficiency consultant after all.  I want this process to be as smooth as possible.  Lets use a Configuration  Manager task sequence for this.

I am sure there are a couple different ways that this could be deployed.  I will explain my reasons for choosing the methods I chose as I describe them.  First we build ourselves a collection of computers.  (I am currently working on automating this portion as well.  I will have a future post on that.)  Next we need to create a package that holds our script.  We do not need to create a program for the package, because we will be running it from a Task Sequence.  (I will be automating the creation of the collection, package, and task sequence in the near future as well.)    Now that we have a collection and a package created and the content distributed to our distribution points, we will create and deploy the task sequence.

We just need to create a new, blank task sequence.  We are going to use the “Run Command Line” task.  I chose this task as opposed to a Run PowerShell Script task (The ConfigMgr or MDT version), because I wanted to utilize the “Run this step as the following account” option that is made available to use in this task.  I chose this option over trying to worry about providing credentials in a script.

We want to configure the task to look as follows:

PS TS.PNG

 

The command that is running the script is as follows:

powershell.exe -executionpolicy bypass -file .\BuildDriverPackages.ps1 PrimarySiteServer DistributionPoint1,DistributionPoint2 \\server\share1 \\server\share2

Now that we have a task sequence created, we can deploy it to our collection.  If we deploy this as a required deployment, then any Windows 8.1 or Windows 10 device that gets added to this collection, will automatically get a Driver Package created for it.

And there we have it.  A PowerShell script that will collect our drivers for us, copy them to our source repository, and build a driver package for us.  In the end we should have:

  • Drivers imported with categories:drivers.PNG
  • A distributed driver package named after the hardware model:

package

  • A driver source folder named after the hardware model, and a driver package location also named after the hardware model:

 

Please don’t hesitate to reach out with any questions or suggestions.

4 thoughts on “Automatically Collect Drivers and Build Configuration Manager (Current Branch) Driver Packages with PowerShell

  1. Pingback: Building Configuration Manager Driver Packages for Windows 7 with PowerShell and Double Driver | To the Cloud and Back

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 )

Connecting to %s