How To: Inject Drivers from USB During a ConfigMgr Operating System Task Sequence

ConfigMgr OSD does a great job of injecting drivers ‘on the fly’ into your OS Deployment process. For example, you can create task sequence steps with conditional statements to apply drivers for a specific model. That’s great for your standard build, but how do you handle those one-offs, those non-standard builds? Here’s a process that you can you for those non-standard builds, or for that hardware that you’re testing, but haven’t quite committed to being a standard yet.  All we need is a vbScript, raw drivers, and an additional step in your task sequence (haven’t tested with MDT, but should work there as well). The following process ONLY works on Windows 7 and Windows Server 2008 R2. If there is enough demand, I’ll create a similar script for previous Operating System versions.

Step 1 – Create a USB folder with raw drivers for the desired hardware.

  • Create a folder in the root of a USB drive named “ExportedDrivers”
  • Copy desired drivers to this folder. You can create subfolders to help with organization if you’d like. Please note that *everything* in the ExportedDrivers AND ALL SUBFOLDERS will be processed, so try to keep the folder structure organized, and to ONLY include the desired raw drivers.
  • Your folder should look similar to this:
  • We have a few extra folders here to keep things organized, but you can just put them in the root of “ExportedDrivers” if desired.

Step 2 – Create a package with ImportCustomDrivers.vbs

  • Create a new Package (or just add this file to an existing package)
  • Download ImportCustomDrivers.txt, and rename to ImportCustomDrivers.vbs.
  • Send to DPs.

Step 3 – Add new step to OSD Task Sequence

  • This step should run in WinPE, just before all other “Apply Driver Package”or “Auto Apply Drivers” step.
  • Your Task Sequence step would look similar to this:
  • Depending on your environment, you may want to enable the ‘continue on error’ checkbox on the Options tab. If the script attempts to import a driver that does not apply to the current operating system, it will return a failure exit code.
  • If you have ADDITIONAL “Apply Driver Package”, or “Auto Apply Drivers”steps, and you want to skip these steps if we import drivers from the USB, enter a conditional where Task sequence variable “OSDCustomDriversApplied” not equals “True” (this variable is set in the .vbs when it runs).

Now that you have your task sequence configured, insert the USB drive into the test system and launch a test build. At the “Add Custom Drivers…” step. you will see a command prompt that shows the status of the drivers that are being injected.

  • In WinPE, two log files will be created in X:\Windows\Temp\SMSTSLog:
    • OSD_CustomDrivers.log – this is the log for the vbscript
    • DISMCustomImport.log – this is the out file from the DISM command to import everything under USBDRIVE:\ExportedDrivers\
  • The log files will also be copied to the ConfigMgr log file directory to allow for post-image troubleshooting.

Again, this process is meant for those one-off scenarios. If you plan to fully support a platform, be sure to handle driver installation using ConfigMgr driver management.

Greg

ramseyg@hotmail.com

Source Code:


'Use this script to import custom drivers for Server 2008 R2, Win7, and newer - full blog post on https://gregramsey.wordpress.com/
'Created by: Greg Ramsey

Log "ImportCustomDrivers - Start"
strComputer = "."
strDriverFolder = "ExportedDrivers"
intReturnCode = 0
intFinalReturnCode = 0
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = WScript.CreateObject("WScript.Shell")
Set colDisks = objWMIService.ExecQuery("Select * from Win32_LogicalDisk")

'enum each drive letter, and see if strDriverFolder exists in the root.
For Each objDisk In colDisks
'Check each drive letter to see if there is a
If objFSO.FolderExists(objDisk.DeviceID & "\" & strDriverFolder) Then
'this will only run in a TS environment, so fail if we can't connect to sms.tsenvironment
Log vbTab & "Connecting to SMS.TSEnvironment"
Set oTSEnv = CreateObject("Microsoft.SMS.TSEnvironment")
If err.number <> 0 Then
Log vbTAB & "Unable to connect to Microsoft.SMS.TSEnvironment"
Log "ImportCustomDrivers - End"
WScript.quit(err.number)
Else
'prepare the command line, and launch the DISM command
Log vbTAB & objDisk.DeviceID & "\" & strDriverFolder & " Exists, Importing drivers.."
strCommand = CStr("Dism /image:" & oTSEnv("OSDTARGETSYSTEMDRIVE") & "\ /logpath:%windir%\temp\smstslog\DismCustomImport.log /Add-Driver /driver:" & objDisk.DeviceID & "\" & strDriverFolder & " /recurse")
Log vbTAB & "Preparing to run the following command: " & strCommand
intReturnCode = oShell.Run(strCommand, 1, True)
Log vbTAB & "Return Code = " & intReturnCode
Log vbTAB & "Setting TS Variable OSDCustomDriversApplied = True"
oTSEnv("OSDCustomDriversApplied") = "True"
End If
Else
'no custom drivers exist
End If
'slightly cheesy - if more than one drive have the special folder, the DISM command will run more than once
' so we're using this to capture if ANY of the exit code are <> 0, so we can capture that if there are any failures
' you'll have to review the %windir%\temp\smstslog\DISMCustomImport.log for details
If intReturnCode <> 0 Then intFinalReturnCode = intReturnCode
Next
Log "Final Return code = " & intFinalReturnCode
Log "ImportCustomDrivers - End"
WScript.Quit(intFinalReturnCode)

'a simple logging subroutine
Sub Log(message)
WScript.Echo message
Const ForAppending = 8
Set WshShell = CreateObject("WScript.Shell")
strSystemRoot = WshShell.ExpandEnvironmentStrings("%SystemRoot%")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(strSystemRoot & "\Temp\SMSTSLog\") Then
objFSO.CreateFolder(strSystemRoot & "\Temp\SMSTSLog\")
End If
'Create Output Log
stroutputlog = strSystemRoot & "\temp\SMSTSLog\OSD_CustomDrivers.log"
Set objTextFile = objFSO.OpenTextFile(strOutputLog, ForAppending, True)
On Error Resume Next
txtstatus.value = Trim(Replace((message & " " & Now()), vbTab, ""))
On Error Goto 0
message = Now() & " " & message
'
' Log the given message
'
objTextFile.writeline(message)
objTextFile.Close

End Sub