In ConfigMgr, when doing OS Deployment from HTTPS enabled DPs, or via Peer Cache (uses HTTPS too), or via BranchCache (encrypted data + encrypted transfers), you will find that using traditional driver packages, with thousands of small files, is not going as fast as you would like. In fact, a single deployment can take a good 5-10 minutes to download a large driver package depending on the environment.
Note: While this post deals with driver packages in ConfigMgr, you can apply the same strategy for application packages that have many small files, or simply really large applications that could benefit from a bit of compression. For example, I've worked with organizations that create wim images for their larger applications, and instead of extracting the wim prior to running the application setup, they simply mount the wim image, and run the installer from that one.
Update, March 1, 2020: Maurice Daly is has updated his Driver Automation Tool to create WIM, ZIP or 7-zip versions of the driver packages too. It's a fantastic tool, I highly recommend using it.
TL;DR
By switching your ConfigMgr driver packages to archived versions, you don't only make them much smaller, but also increases overall download speed and peer-to-peer efficiency. Usually between 5-10 times faster depending on content source. WIM and Zip will give you much better deduplication rates, and better P2P performance. But 7-zip format will reduce package size a bit more.
Some Real-World Data
In this example, I was using BranchCache as the peer-to-peer solution for ConfigMgr OSD, but you'll see similar behavior for normal HTTPS downloads either directly from the DP, or HTTPS downloads via Peer Cache.
As an example: When deploying a Dell Latitude 7250, with its 1 GB driver package (1000+ files) in my lab. The driver step alone took 7 minutes, and this was on a 155 mbit network with a remote DP. Deploying five of them at the same time, ended up with a total of 10 minutes for the drivers step (peering saved me some WAN bandwidth). Bottom line, downloading, or peering large packages with many small files is just not very efficient. But it can be much better…
Note: When zipping driver packages you do lose the single instance store benefits of the ConfigMgr Content Library for these packages, but in my testing the benefits of reducing package size by zipping driver packages totally outweighs the single instance store. As an example, I imported 26 driver models the traditional way, their source size was 43 GB, and the Content Library grew with 29 GB. For the zipped versions, even on the lowest compression rate, the resulting size was 22 GB. When adding data deduplication to the distribution point, another 8 GB was saved, and disk usage was down to 14 GB.
Zip or WIM your Driver Packages
Many organizations have already switched to use legacy packages for the drivers, and have DISM just inject them during the task sequence. But why not take it one step further, and simply zip the content in your driver packages.
You can either use PowerShell (5) or 7-Zip to archive the driver package into an individual zip or WIM file. If you are optimizing for BranchCache data deduplication efficiency among many packages, use the Compress-Archive cmdlet with compression level set to Fastest, and for 7-Zip, use the zip format with the deflate algorithm. BranchCache really likes these algorithms, and is quite good in figuring out deltas for these formats too. If you are optimizing for fastest possible deployments, and don't pre-cache lot of data, 7-zip on ultra compression will create quite small packages.
Note: While it may be tempting to use super-high compression algorithms, doing so will lower data deduplication efficiency, and delta updates of packages (BranchCache uses data deduplication). That being said, higher compression algorithms will usually reduce the size with another 30 percent or so, so for direct download from DP having data deduplication enabled, or from Peer Cache, which can't do data deduplication, you might want to use it.
Below is the syntax for Compress-Archive cmdlet:
# Compress a single driver package
Compress-Archive -Path "E:\Sources\OSD\DriverSources\Dell\Latitude 7250" -DestinationPath "E:\Sources\OSD\DriverSources\Dell\Latitude 7250\Drivers.zip" -CompressionLevel Fastest
# Compress multiple driver packages, looping through a sources folder
$DriverSources = Get-ChildItem "E:\Sources\OSD\DriverSources\Dell"
$DriverPackages = "E:\Sources\OSD\DriverPackages\Dell"
Foreach ($folder in $DriverSources){
New-Item -ItemType Directory "$DriverPackages\$($folder.Name)"
Compress-Archive -Path $folder.FullName -DestinationPath "$DriverPackages\$($folder.Name)\Drivers.zip" -CompressionLevel Fastest
}
After archiving my 1 GB driver package for the Dell Latitude 7250 model, the resulting drivers.zip file was about 425 MB in size.


After creating the drivers.zip file, you just copy it to a folder, and create a new legacy package in ConfigMgr using that folder as the source. And, don't forget to distribute the package 🙂

Modify your Task Sequence
The final step is to configure your task sequence to use the Zip-version of your driver package. Basically it will just download the package first, and then extract it using PowerShell.
Note: If you follow this example, don't forget to add PowerShell to your boot image(s), or the Expand-Archive command is not going to work very well 🙂
There are many options to get the download/extraction going, but for example a regular "Run Command Line" action together with a WMI condition, will do just fine. The command line I used to extract the content of the Zip-version of the driver package is the following:
PowerShell -ExecutionPolicy Bypass -Command "Expand-Archive -Path .\Drivers.zip -DestinationPath %_SMSTSMDataPath%\Drivers"

The final step is to instruct the task sequence to inject the drivers that were extracted into the driver store using DISM. For this you add another Run Command Line action, with the following command:
DISM.exe /Image:%OSDTargetSystemDrive%\ /Add-Driver /Driver:%_SMSTSMDataPath%\Drivers\ /Recurse /logpath:%_SMSTSLogPath%\dism.log
Don't forget to add a condition to the command so it only runs if the folder exist. You don't want the task sequence to error just because you deployed a machine where you didn't need to use any drivers (or forgot to add them).


Additional Reading
If you want to learn more on how Data Deduplication and BranchCache works together I recommend reading the below post from Mike Terrill.
Getting Network Efficiency from Data Deduplication and BranchCache
https://miketerrill.net/2019/12/08/getting-network-efficiency-from-data-deduplication-and-branchcache
Jörgen Nilsson also have a good post on using 7-Zip for ConfigMgr Drivers
Distribute Drivers at Mach speed
Distribute Drivers at Mach speed – CCMEXEC.COM – Enterprise Mobility
Hi Johan,
could you explain how add drivers using WIM file instead of .zip?
thanks so much!
Hi David,
The modern driver automation tool from Maurice and Nickolaj nicely takes care of creating WIM files of your per-model driver packages. I do have some examples offline as well, please reach out to me on LinkedIn if you would like a copy.
Being new to SCCM, I have downloaded the driver cab from HP, and used HP's HPIA program to download the latest drivers. My question is what do I set as my root folder to zip up? Do I start where the list of folders like, audio, chipset, graphics and so forth are at, or do I start at the top of the zip, and zip everything using 7zip? I tried to use Driver automation tool, but even with it set to download only, I watched it download all of the files, extract them, and then delete them right back out… Read more »
The Driver Automation Tool is useful to download, and add drivers to either MDT or ConfigMgr. Since the ConfigMgr setup options has more features, I usually use that one even when using MDT.
/ Johan
Hey Johan,
I noticed the Pause steps in your TS can you confirm if this is required?
No, that's just what I'm using to speed up testing and/or troubleshooting.
Has anyone tried this with an OS Upgrade Package when using a CMG DP?
One of our customers are using the modern driver management with compressed driver packages via IPU from their CMG.
Using the Driver Automation Tool, it generates the following directories when downloading and uploading the folder to the network directory, which is: Dell\Latitude E5430-vPro-Windows10-x64-A01\StandardPkg\Windows10-A01\E5430\win10 – e inside that folder contains:
win10 (folder), driverarchivemanifest.xsd, Manifest.xml, Readme.txt.
Within win10, we have: x64 (folder) and x86 (folder), do I need to modify this? or the script in the task sequence can find the drivers entering all the subfolders?
The Invoke-CMApplyDriverPackage.ps1 takes care of locating the driver archive and unpacking it. That script was designed for packages created by the Driver Automation Tool, but will work with custom driver packages too as long as you configure the settings right.
Hi, thanks for this great write up (I think it is worth updating your post to mention the 64-bit 7-Zip SFX recompiled by Jorgen Nilsson https://ccmexec.com/2020/03/distribute-drivers-at-mach-speed) Anyway, I have two questions: 1) When using DISM /Add-Drivers, we often see Error 2 (indicating one or more drivers failed to import) however, if this is supressed it does not cause a problem to the device, so seems this error can be ignored. 2) When the same drivers are imported into SCCM and an Apply Drivers task is used, there are no errors. So does this indicate SCCM TS Engine is supressed these… Read more »
Hi Mike, thanks for the tip. Added a link to Jorgen's post.
As far as the dism /add-driver issues when drivers are broken for whatever reason goes, I recommend validate the driver content prior to create the package in ConfigMgr. Can easily be done by importing them into an "empty" MDT deployment share via PowerShell. It will tell you which drivers that are not ok. As far as how ConfigMgr deals with the suppression of errors I don't know. Their default inject option is not to use dism, but rather their own executable.
Hey Johan, I know you posted this long ago, and I'm not using the zip format, but I am using the same dism command line to install the drivers. They appear to be installing fine but when I look at the status messages, on some systems, I get an error code 3 (The system cannot find the path specified). I thought it might be the log path but I've tried hardcoding it and still see the error. Have you ever seen this before?
As long as there are drivers in that folder the dism command should run fine. Make sure you have a condition on the step to only run if the drivers folder is present.
Interesting…I created something similar about 2 years ago for use with MDT. However I use some of the variables available and query a web service to get the correct ZIP file name, and download that from a web server.
Great minds think alike 🙂
Good stuff….With vendors like Dell that offer enterprise driver packs in the form of cab files, I suppose you could do something similar using their cab files and the expand command.
Johan, we've done something very similar to this in the past but instead of using .zip files, we've created .WIM files of the content and put that in a package. We then apply that wim to a location on the c: drive during build time and then DISM the drivers in. The nice thing about WIMs is if you have multiple models sharing the same drivers, you get the single instance store in that WIM file itself, (not on the content library of course). And as we all know, you can also have multiple indexes for those different models. I… Read more »
Yes, I'm planning on evaluating WIM as format as well. For Data Deduplication and BranchCache the compression compatibility, and delta capability, is more important than how high it can be.
jeff is there a blog you followed for that?
The never versions of the driver automation tool generates wim images, and they turned out to be more efficient than zip files.
Hey Johan, do you think this could work in conjunction with scconfigmgr's dynamic driver install via webservice?
Yes, Maurice is working on a version with ZIP support. I'm currently testing a beta version of it, and it looks great so far.
Hi Johan, I also want to check that functionality, created the zipped packages with the Modern Driver Management Tool, but I'm lost to apply that in my sequence. Do you have some guidance regarding that?. Thanks in advance.
Just add the Invoke-CMApplyDriverPackage.ps1 to a package, and run it before Setup Windows and ConfigMgr. See this image.
Hello Johan, another great post! I did this the same thing an year ago for a customer to save space on SCCM server and DPs. I used 7z compression and the size was down to 30% on an average for driver packages.
Thanks 🙂
Will this two step process be faster than just the one step? What was your time reduction?
For the driver package I tested it was 7 minutes vs. 1 minute. So quite the difference. injecting at the same time as extracting will be same same, but I like to have the dism command separate.
Thanks for the post! Other than me failing to rename your driver.zip in the extraction step it worked great.
Glad to hear 🙂
Hello Johan,
Thank you for the post. This scenario would work even if we replace standard SMSTSDownloader with ACP?
Thanks,
Sushant
Yes, that works. I have tested with the BITS ACP from 2Pint Software, but any ACP will work. It's just a regular run command line action with a package.
Thanks