Written Matthew Teegarden (@TheEmptyGarden).
The goal of this article is to show you how to move from managing ConfigMgr driver packages to something much more dynamic. You will no longer need to edit your task sequences with additional driver package steps. Sound fun? Yes, yes it does.
Recently at my local System Center User Group – MNSCUG.ORG – I was told that the cool kids don't use the Driver Packages node anymore..while I was demonstrating some tools that automatically download and import driver packages into the Driver Package node!! Awkward.
The reason why ConfigMgr (SCCM) Driver Packages aren't so cool is the amount of data that gets put into the database.
So, I will now be a cool kid and not use the Driver Package node. You too, can be a cool kid. Read on.
Before we begin I must acknowledge and thank the following people:
- MVP Kim Oppalfens @TheWMIGuy – for the inspiration: http://www.oscc.be/sccm/osd/The-holy-grail-of-ConfigMgr-diver-management,-or-whatever-you-want-to-call-it/
- MVP Peter van der Woude @pvanderwoude has a great post on using PowerShell for WMI Eventing: http://www.petervanderwoude.nl/post/category/wmi-eventing/
The Basic steps
- Generate an XML file with a list of packages that contain drivers. NOTE: We are just using regular ConfigMgr Packages not the Driver Package node
- In the Task Sequence add a step to read the XML file and determine the correct package based on model, OS, and architecture
- Download the correct package to C:Drivers
- Use DISM to inject the drivers
Generate XML with list of packages that contain drivers
Download all of the drivers packages to separate folder using a standard naming convention. Here is an example of creating folder for Driver Source > Operating System > Manufacturer > Model
Create a package for each driver model using a naming convention such as this:
The packages will just point to a source folder that includes the drivers as shown below. You do not need to create a program.
Notice that there is a package called "Drivers – Empty for default download". This is the package that will get downloaded if there isn't a match for the model, operating system, and architecture. Make sure to distribute all of your packages with "Drivers – " in them to the OSD distribution points. This includes the "Drivers – Empty for default download" package.
Create PowerShell script
Now that there is a standard naming convention for the Driver Packages, it is time to write a PowerShell script to generate an XML with the PackageID and Package Name. This is done outside the task sequence because the task sequence does not have access to query ConfigMgr.
In the folder where you keep all your packages create a new folder called "OSD – Get-DriverPackage"
In ConfigMgr create a package called "OSD – GetDriverPackage" pointing to the above source folder. You do not need to create a program.
When I teach PowerShell I always tell people that getting your script to do what you want is about 60% of the work. Making sure that it will always work and including logging takes up the other 40%. Error handling and logging take a long time. Having a reusable template should be viewed as a requirement.
Kim has a logging script called Log4Net. I already use a template that you can see below. In either case, pick something that is repeatable so that all your scripts include error handling and logging.
The PowerShell-Template.ps1 script: http://github.com/DeploymentResearch/DRFiles/blob/master/Scripts/PowerShell-Template.ps1
Save the Set-DriverPackageXML.ps1 (link below) to your "OSD – Get-DriverPackage" folder that was created in the above step. Don't forget to change the variables in the script to match your environment. Run the script to ensure that the XML file gets updated.
The Set-DriverPackageXML.ps1 script: http://github.com/DeploymentResearch/DRFiles/blob/master/Scripts/Set-DriverPackageXML.ps1
Create WMI Event Filter
The next step is to automatically run the Set-DriverPackageXML.ps1 script anytime a ConfigMgr Package with the name "Driver – %" is created, modified, or deleted. To do this run the following script to create the WMI EventFilter, CommandLineEventConsumer, and the FilterToConsumerBinding.
NOTE: You could use ConfigMgr status filter rules, but you would need to create one each event (delete, modify, and create). Also, the ConfigMgr Status Filter Rules don't allow for any filtering. So, the WMI Eventing is the way to go
In the script you will see a line like this: "SELECT * FROM __InstanceOperationEvent Within 60…" The Within 60 means that the script will poll every 60 seconds. That is probably as much as you want. Though, in a small test environment you could go "SELECT * FROM __InstanceOperationEvent Within 5".
Open the following script as administrator (elevated rights) and run it.
The Set-WMIEventingForSet-DriverPackageXML.ps1 script: http://github.com/DeploymentResearch/DRFiles/blob/master/Scripts/Set-WMIEventingForSet-DriverPackageXML.ps1
Time to test it out
Create a new "Drivers – %" package. Look for an updated "TEE-CM1SCCMPackages$OSD – Get-DriverPackageDriverpackages.xml file. If you don't see one it is time to troubleshoot. Open the C:WindowsTempSet-DriverPackageXML.log and investigate. The package also should have a new updated distribution time.
Modify the name of a "Drivers – %" package. Look for an updated "TEE-CM1SCCMPackages$OSD – Get-DriverPackageDriverpackages.xml file. If you don't see one it is time to troubleshoot. Open the C:WindowsTempSet-DriverPackageXML.log and investig
ate. The package also should have a new updated distribution time.
Delete a "Drivers – %" package. Look for an updated "TEE-CM1SCCMPackages$OSD – Get-DriverPackageDriverpackages.xml file. If you don't see one it is time to troubleshoot. Open the C:WindowsTempSet-DriverPackageXML.log and investigate. The package also should have a new updated distribution time.
So far, what has been accomplished is the automatic updated of the Driverpackages.xml file whenever a SCCM Package with the name "Drivers – %" is created, modified, or deleted. Also, the package containing the XML file is automatically refreshed on the Distribution Points.
Get the driver package during a task sequence
Here is what the result of an OSD task sequence steps for drivers will look like
Save the Get-DriverPackages.ps1 script (link below) to the "OSD – Set-DriverPackageXML" folder. At this point that folder will have two PS1 scripts and one XML.
The Get-DriverPackages.ps1 script will read the XML, look for the architecture (x86 or x64) of the Operating System, get the Operating System name, and get the computer model.
The script will then compare the findings with the names of the Driver Packages. If a match is found, the OSDDownloadDownloadPackages Task Sequence variable will be populated with the PackageID.
If there is not a match the OSDDownloadDownloadPackages Task Sequence variable will be populated with "NoDriverPackageFound"
The Get-DriverPackages.ps1 script: http://github.com/DeploymentResearch/DRFiles/blob/master/Scripts/Get-DriverPackages.ps1
The task sequence step will look like this:
Download Package Content
Now that the PackageID that contains the required drivers has been identified, it is time to download them to C:Drivers
The Download Package Content Task Sequence step will look like this:
Notice it is set to download the "Drivers – Empty for default download" The PowerShell script from the previous step will change the package from "Drivers – Empty for default download" to a true driver package if one was found. This is done by replacing the Task Sequence variable OSDDownloadDownloadPackages with the PackageID that matched the model, architecture, and operating system of the device.
The last step is to run DISM to inject the drivers.
You create a Run Command Line Task Sequence step with the following:
DISM.exe /Image:%OSDTargetSystemDrive%\ /Add-Driver /Driver:C:\Drivers /Recurse /logpath:%_SMSTSLogPath%\dism.log
And there you have it. 21 pages and over 400 lines of code later we are done! Now you will never have to modify a task sequence and add driver packages to it. You also are keeping your SCCM database clean by not importing driver packages. Finally, you have created a very dynamic and 'cool kid' way of downloading and importing drivers during OSD. This may even qualify as shiny!