Modern Driver Management and How I Barely Got It Working – Some Lessons Learned

Several months ago, my boss came back from Microsoft Ignite where he “drank the Kool-Aid” big time. We had been telling him about all of the amazing things that were being released to help with the move to Modern Windows Management with Windows 10 for months but he got to hear it directly from some of the experts and got really excited. One of the things he suggested looking into came from a session with Mike Nystrom and Johan Arwidmark called Expert-level Windows 10 deployment (Skip to 50:12 for driver management). I had come across several posts discussing this technique but hadn’t attempted it previously but got to work testing it.

Here’s some background that will come into play a little later on.

  • I am no longer using reference images, just the original media from Microsoft – in this case, I’m using 1709.
  • The 2 areas that I had issues with were the new “Download Driver Packages” step and the DISM /Add-Driver command referred to in the blogs below.
  • I use the “Access content directly from the distribution point when needed by the running task sequence” setting on my OSD deployments

The Setup

To start, you should follow one of these blogs to get set up – others have written great blogs about this technique so why not just refer to them? Fair warning, some are more automated than others and some go into more detail than others. I would suggest reading all of them to get familiar with the concepts then build and test the basic setup before trying to use the automated versions.

There are lots of variations of these posts and the techniques have evolved since they were first posted. The general idea is that you download your hardware driver bundles from your hardware manufacturers, then import them into SCCM as Packages, not Driver Packages. Then you use DISM to apply the drivers to your OS image before it is installed during your OSD task sequence.

My Challenges

Download Package Content

This step lets you download content from one or more packages (separate steps for each) and save the path into a shared variable. You can then reference the variable in later steps like Apply Driver Package or the custom DISM command from the above blogs. What isn’t mentioned in the Microsoft documentation is that this step cannot be used when the Deployment option of “Access content directly from the distribution point when needed by the running task sequence. In a case with Premier Support, the resolution was to have the documentation updated to include better verbiage. I haven’t seen any updates yet, but have found that the Microsoft Documents folks have an open source option that allows for community edits. I may have to look into that soon. Here’s a link to the Docs Contributor Guide.

The Workaround

  • This assumes that you are using Packages, not Driver Packages.
  • Create a Run Command Line TS step
  • Enter this command line:
  • Change %_SMSTSMDataPath% to any pre-defined path you choose. This is the default location that SCCM uses. Whatever you specify here will be used in the DISM step later.

Apply Driver Package

As I mentioned, I had issues with the custom DISM commands that everyone was using, so I was using Apply Driver Package along with my xcopy command line to “install” a dummy package to create the entry in the unattend.xml file that setup uses to find drivers.

This step takes the driver package and makes it available to Windows setup. If you check Apply driver package via running DISM with recurse option Windows setup will attempt to use DISM to import the drivers into the OS image that was staged in the Apply Operating System Image step. It will also add this entry to the unattend.xml file with the path to the drivers to allow setup to grab them during install, so if you didn’t check the DISM option, it would still be able to grab the cached drivers. Keep this in mind because it helped lead me to my issue.

Apply Operating System Image

Here’s where it all fell apart for me. We have always used reference images. Most blogs about OSD assume reference images are used. Since we are hoping to keep up with the Windows release cadence, I decided to see how well things went just using the default OS from Microsoft to save us some back-end support efforts moving forward. I swapped the reference image for the default image in the TS but there are 2 options available for this step. Generally you set them in the MDT TS wizard and don’t mess with them unless you’ve updated your image so I used Microsoft’s guidance on this:

Apply operating system from a captured image
Installs an operating system image that has previously been captured. Click Browse to open the Select a package dialog box, and then select the existing image package you want to install. If multiple images are associated with the specified Image package, use the drop-down list to specify the associated image that will be used for this deployment. You can view basic information about each existing image by clicking on the image.

Apply operating system image from an original installation source
Installs an operating system using an original installation source. Click Browse to open the Select and Operating System Install Package dialog box, and then select the existing operating system installation package you want to use. You can view basic information about each existing image source by clicking on the image source. The associated image source properties are displayed in the results pane at the bottom of the dialog box. If there are multiple editions associated with the specified package, use the drop-down list to specify the associated Edition that is used.

Here’s the dialog box:

Logically, I selected door #2 Apply operating system image from an original installation source since it perfectly describes what I was doing. What I failed to notice was that when you click Browse to select your image, you are presented with all of your Upgrade Operating System Packages, not your Operating System Images. (Note: I initially didn’t include “Upgrade” in the name of the Image, which only compounded this issue).

As you may know, the media is different for these two OS types. Operating System Images uses the Install.wim from the source media while Upgrade Packages uses the full source folder for the OS.

When Apply Operating System Image would run, with my Original Installation Source (Upgrade Package), it would apply in a different way than the Captured Image option causing the Apply Driver Package step (which uses DISM) as well as the Run Command Line step from the Modern Driver Management blogs to fail. I switched to using the captured media option, and selected my original Windows 10 1709 media and the Apply Driver Package and the DISM command line began working as expected. I am now well on the road to completing the automation of Modern Driver Management for our environment.

Note: At the time of this posting, I have a case open with Microsoft Premier Support to determine if this is a bug or by design (with really poor documentation/verbiage). I will update once I hear back.


  • Reply
    February 26, 2018 at 12:32 pm

    Glad I checked your site, i have an explanation for what is going on here. When using an upgrade OS package to install the step of “apply OS” doesnt lay down the image after wiping the disk, it just preps the drive, wipes it, puts the content under the _smstasksequence folder etc. DISM doesnt work at all here because there is no offline image present for it to run against… Half way through “setup windows” there actually is, but since you cant put a command in the middle of the step, there is no oppertunity to dism the OS. Kind of annoying… In a way, you just went back to reference images. So I presume you have two packages pointing to the same content.

    I was able to get this to work by staging the drivers after the apply image step but before the setup operating system step. We use a customized version of the install.wim that includes extending the drivers search folders to include our drivers folder. This allows us to use “modern driver management” and still retain a single image package (operating system upgrade package) that handles OSD and Upgrades seemlessly. If you want I can share my script I use to modify the install.wim… but here is the core of the reg hack:

    #Registry Fix to add drivers folder to driver store.

    Write-host Loading Software Hive from Image

    reg load HKLM\HKLMTemp $PATH\MOUNT\Windows\System32\config\software

    Write-output “############################” >> $PATH\processlog.log
    Write-output “# Current Image devicepath #” >> $PATH\processlog.log
    Write-output “############################” >> $PATH\processlog.log
    REG Query HKEY_LOCAL_MACHINE\HKLMTEMP\Microsoft\Windows\CurrentVersion\ /v devicepath >> $PATH\processlog.log

    REG ADD HKEY_LOCAL_MACHINE\HKLMTEMP\Microsoft\Windows\CurrentVersion /v DevicePath /t REG_EXPAND_SZ /d “%SystemRoot%\inf;%Systemdrive%\Drivers” /f

    Write-output “############################” >> $PATH\processlog.log
    Write-output “# NEW Image devicepath #” >> $PATH\processlog.log
    Write-output “############################” >> $PATH\processlog.log
    REG Query HKEY_LOCAL_MACHINE\HKLMTEMP\Microsoft\Windows\CurrentVersion\ /v devicepath >> $PATH\processlog.log
    Write-output “############################” >> $PATH\processlog.log

    reg unload HKLM\HKLMTemp

    Thats it really, mount the hive, update the path to include whatever, and you are done, works like a charm. I didnt have much success with getting the unnatend.xml to work at all so i went this route.

    The added bonus is you can easily preload the machine with drivers you might think the system needs for peripherals. The PNP engine will parse that folder for drivers when it detects new devices.

    • Reply
      Adam Gross
      February 26, 2018 at 1:11 pm

      James, Thanks for the added explanation. What you described was indeed what I discovered while digging into this issue. Ultimately, it just comes down to poor verbiage in the TS console, in addition to me not properly labeling my upgrade package as such in the console, that led to me selecting the incorrect image type. I guess you are the same James Leroux that I interacted with over on Kim Oppalfens’ site:,-or-whatever-you-want-to-call-it/. Your posts there helped me along.

      An alternative method (See Apply Driver Package section above for more details) that I found works (only if you use Download Content as Needed) is to create a “Dummy” driver package that just has 1 generic INF file in it. Add an “Apply Driver Package” step to the TS and point to the Dummy package for the source. Be sure to click “Install driver package via running DISM with recurse option”. Then use the download package content steps for all of your other driver packages and copy them into %_SMSTSMDataPath%\Drivers. This will stage the drivers in the same location as your Dummy package. When you run the Setup Windows and Configuration Manager step, unattend.XML gets updated with the code above. Without the Dummy package, you can’t manually add the above settings to the unattend.xml file – it get’s overwritten. Anyway, this is yet another alternative to making this work.

      Thanks for your response(s) as well as the PowerShell code you sent me. If I make a post about using it, I will be sure to credit you.

  • Reply
    James Leroux
    February 26, 2018 at 8:50 pm

    oh so there is a check during the dynamic building of the xml that tosses the code out if it finds no drivers in the referenced source? unreal… Ill try to spin up a task sequence using this method and see if I can get it working… Although honestly. using the registry method works great and sidesteps these issues.

    • Reply
      Adam Gross
      February 26, 2018 at 8:58 pm

      “Unreal” certainly isn’t the word I used when I was knee deep trying to sort it out!

  • Reply
    James Leroux
    February 26, 2018 at 8:51 pm

    oh an yeah thats me on there.. 🙂 glad i was useful.

  • Reply
    March 6, 2018 at 7:35 am

    Just a followup.. I experimented a bit already with using those driver path statements, and tried again given your apparent success.. I traced the unattend.xml that gets dynamically generated during the install, and unfortunately I found no trace of those settings getting imported and utilized… Are you 100% sure this was the case? I’m interested in a more precise explanation of the steps since I am not sure how you are connecting your copied folder, to the “apply driver package” step, and replacing the import command with the folder containing the actual drivers, not the referenced dummy package. I’m afraid I just can’t figure it out.

    Bear in mind I am using “the full media” version. So like we were talking before there is no opportunity to apply dism to an offline image, as it does not present itself at the “apply operating system stage” in this case… (it actually is available part way through the “setup windows” phase, but you can only apply drivers with DISM via command line at the precise moment during, and not after)

    What I was hoping to do was use the unattend.xml to feed setup.exe a source path to import drivers from during the setup windows phase, but all attempts to do so have failed.

    What I suspect is, that since you are back to using a reference image, and straight DISM works fine, that the other steps you are doing regarding the unattend.xml and content copying are not really needed. Using a dism command to reference the package download location variable works perfectly well if you have applied a reference image OS package as you have discovered.. Unless I have missed something (strong possibility)…

    It would be nice if MS just gave us a field to use for the setup windows phase to reference offline drivers… they have one for the in-place upgrade TS object, and its just a command line option.

    Here is a half assed summary of what my TS does:

    “Apply OS Image” : using an “Original Source”/OS upgrade package… This wipes the drive (except for USMT data if present) lays down the package contents in a folder.
    Run the driver package script, overrights the package download variable with the machine appropriate driver package

    3 download driver package content saving the location to a variable

    4 move the content via the variable, to a standard location (c:\drivers)

    MDT toolkit step

    6 MDT gather step

    apply windows settings / apply network settings (data from TS env. imported into unnatend.xml)
    setup windows and config mgr (using the dynamically generated xml)

    Since my image contains a modified registry setting, the “drivers” folder is scanned during the PNP phase of the windows setup, and the drivers are installed. This is not much different than preloading the driver store via dism in terms of how and when the OS installs the drivers.

    I would LOVE to get away without having to modify the registry in this way, but it does have other tangible benefits as you can drop anything into this folder if you want a system to be primed to install drivers on demand for future devices.

    Feel free to email me directly..
    [email protected]

  • Reply
    James Leroux
    January 24, 2019 at 6:51 am

    Hey Adam I thought I would bump this post with some findings of mine:

    Ran into an issue with a new piece of hardware that would lose network connectivity in the domain join phase of windows setup. Turns out that the PnP engine was not loading the driver that I was supplying in my standard drivers folder until the second reboot (and thus killing my build)… I ended up using the method I had talked about earlier by setting up the stage for a diver import section being generated by referencing a dummy SCCM “Apply driver package” step to seed the unattend.xml, then leveraging the recursive nature of it and stuffing that “c:_smstasksequence\drivers” folder. works basically like this:

    Apply operating system Image (from original source)

    modern driver management steps—> c:\drivers

    apply windows settings

    apply network settings

    apply driver package (classic sccm driver package with a few drivers in it) (make sure you dont click the DISM option, and click on the unsigned drivers option)

    set status 3

    copy folders from c:\drivers that i want to c:_smstasksequence\drivers

    Setup Windows And Configuration Manager

    works great with the “apply operating system from original source” type of apply OS

    The root cause of why this hardware was failing, was due to the fact that windows 10 up to build 1803 supplied an older version of the intel NIC driver (E1D65x64.inf) that matched the PCI ID of the NIC but did not actually function. The built in driver was dated 2016 and version (I217-LM)

    The one that works is version from may of 2018.

    Its a really common NIC so I thought i would post this up in case some intrepid googler runs into this, (like I did).

    In fact that’s the driver I put into my seeding package (the sccm driver package).

    This will be useful for NIC drivers, and possibly storage drivers as well.

    • Reply
      Adam Gross
      January 24, 2019 at 7:30 am

      Have you tried servicing your image with Dynamic Updates? I suspect it will update that driver.

      • Reply
        James Leroux
        January 24, 2019 at 7:58 am

        Well we service already with cumulative but I don’t think that’s what you meant. We are not configured in our SUP to service drivers, have that turned off. The issue with what you are proposing, is that the older driver is still required, as OTHER hardware that we have is not compatible with the new driver. (lol i know…) So both drivers have to exist…. If you import the driver onto your machine you actually end up with two copies under the driverstore file repository folder, under seperate GUIDs. I had considered injecting it into the WIM, but the issue for us is that I don’t want to be cracking open 6 gig wims and redistributing every time we run into something like this. Getting the content out to all our DPs is challenging in our environment.

  • Reply
    James Leroux
    January 28, 2019 at 9:08 am

    Just some fun stuff I’m doing… if you want to copy specific folders, or content in your generic drivers folder, and stage it into the datapath drivers folder….

    So in my implementation of “modern driver management” I stage the driver content into c:
    drivers\ and I have a subfolder where I house custom machine specific scripts and installers, obviously I don’t want the PNP engine trying to parse this folder so….

    run this command:

    powershell.exe -ExecutionPolicy Bypass -Command “dir -Directory $env:OSDISK\Drivers | Where-Object {$ -notlike \”Gac-Customizations\”} | copy-item -Recurse -Destination $ENV:SMSDATAPATH\Drivers”

    You can expand your Where-Object variables to include or exclude things.. just remember to use the \ to exclude any quotes in the values you reference, or the command interpreter will hit the quote and consider that the end of the line you are passing into powershell.

    Not tested yet, but it looks good so far.

  • Reply
    James Leroux
    January 28, 2019 at 11:48 am

    hehe.. well that didn’t work… I forgot how the TS engine expands the variables… plus I wrote the datapath value down wrong 🙂

    powershell.exe -ExecutionPolicy Bypass -Command “dir -Directory %OSDISK%\Drivers | Where-Object {$ -notlike \”Gac-Customizations\”} | copy-item -Recurse -Destination %SMSTSMDATAPATH%\Drivers”

  • Comment

    This site uses Akismet to reduce spam. Learn how your comment data is processed.