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:
- This script was built and tested on the lastest version of Configuration Manager Current Branch and requires the most up to date powershell cmdlets.
- PowerShell remoting(WinRM) must be enabled on the Primary Site Server.
- 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.&nbsp; 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&nbsp; -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:
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:
- A distributed driver package named after the hardware model:
- 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.
Pingback: Building Configuration Manager Driver Packages for Windows 7 with PowerShell and Double Driver | To the Cloud and Back
Looks like there are some things chars missing in the beginning of the script….
LikeLike
Is it possible to provide a link to download the script? That would be great!
LikeLike
The script is complete above. Here is a link to the script on Github. https://gist.github.com/Aeaddy/97a21d767f423276590211d3f30faf34
LikeLike