PLEASE NOTE: Some of the details and features in this post have been superseded. Please review our Modern Driver Management and Modern BIOS Management solutions for up to date information.

Original Post:

So you have deployed your machines with the latest and greatest drivers and BIOS updates. But then the questions of what to do to maintain your systems post deployment?, or do I upgrade the BIOS and drivers as part of an upgrade TS?

These are questions that I have had asked more than a few times of late. In answer to your question, there are several methods to maintain both the BIOS and drivers on the machines but most are vendor specific / developed.

The vendor utilities where available do a good job, the Dell Command Update utility is an excellent example of how to do things right. In some cases however, this means also maintaining a separate master repository for the machines to scan or allowing internet access. When you talk about allowing machines to maintain their driver and BIOS version over the internet, the lack of version control is something that most ConfigMgr admins will complain about. The complaints are justified though, as we all know that system stability can be greatly affected by drivers. So this got me thinking.

Maintaining the BIOS version through our Modern BIOS Management approach has been around for a little while now, so I thought I would extend this maintenance approach to cater for drivers. Below I will show you how you can wrap this up into a single task sequence and then deploy this to your client fleet. You can of course have it re-run as often as you wish within a maintenance window or on-demand for those mobile workers who are seldom in the office.

PowerShell + WebService FTW

Most of you who are familiar with our MDM & MBM solutions will know that we can dynamically determine/download the latest available versions of driver and BIOS packages from ConfigMgr. So I have extended the Invoke-CMApplyDriverPackage.ps1 script used to undertake driver matching and downloading in WinPE with an additional switch, that being the “OSMaintenance” switch. The new switch allows you to tell the script to perform some actions differently, the key action of course being to avoid the DISM step which we cannot undertake on an already deployed OS.

When run with a $true value for the optional OSMaintenance switch works to detect the currently installed version of Windows, this time however not based on the WIM being deployed but on the properties of the NTDLL.DLL. If a matching package is found, it is downloaded and then ready for the next step. Note: This does mean that your task sequence will require a reboot into WinPE for this process to complete, this is due to the method in which we leverage the OSDDownloadContent command.

Applying Drivers

Having taken influence from an earlier post by Mikael Nystrom (https://deploymentbunny.com/2011/05/07/adding-drivers-using-pnputil-and-forfiles/), I have created an additional PowerShell script that leverages the fact we already have a process for downloading the latest available driver package from ConfigMgr. Using the PNPUtil command all we need to do is point the utility at the location to which we downloaded the driver package and your system will then detect and install the latest drivers contained within;

# Apply driver maintenance package
try {
	Write-CMLogEntry -Value "Starting driver installation process" -Severity 1
	Write-CMLogEntry -Value "Reading drivers from $DriverPackagePath" -Severity 1
	if ((Get-ChildItem -Path $DriverPackagePath -Filter *.inf -Recurse).count -gt 0) {
		Get-ChildItem -Path $DriverPackagePath -Filter *.inf -Recurse | ForEach-Object {
			pnputil /add-driver $_.FullName /install
		} | Out-File -FilePath (Join-Path -Path $LogFilePath -ChildPath DriverMaintenance.log) -Force
		Write-CMLogEntry -Value "Driver installation complete. Restart required" -Severity 1
	}
	else {
		Write-CMLogEntry -Value "No driver inf files found in $DriverPackagePath." -Severity 3; exit 1
	}
} catch [System.Exception] {
	Write-CMLogEntry -Value "An error occurred while attempting to apply the driver maintenance package. Error message: $($_.Exception.Message)" -Severity 3; exit 1
}

 

The Task Sequence

In the sequence below there are 8 key steps with others being optional. This will ensure that your machine is kept up to date at all times. Remember this requires no client software and you can tailor logging values to suit your environment.

 

Lets step through the process
  1. Suspend your disk encryption protection to allow for the BIOS to be updated
  2. Restart the computer into WinPE
  3. Run the Invoke-CMDownloadBiosPackage.ps1 PowerShell script.
  4. Run the vendor specific BIOS update script, in this example we are using the Invoke-DellBIOSUpdate.ps1 for Dell system. Restart to apply BIOS. (You can create a group for the BIOS update process and apply a WMI filter using a variable check for NewBIOSAvailable equals “True”. This will prevent the system attempting to flash the BIOS and restart if the version if current)
  5. Run the Invoke-CMApplyDriverPackage.ps1 PowerShell script with the following switches:
    -URI “http://%YOURSERVERNAME%/ConfigMgrWebService/ConfigMgr.asmx” -SecretKey “%YOURSECRETKEY” -Filter “Drivers” -OSMaintenance
  6. Restart the computer into the full OS
  7. Run the Invoke-CMDriverMaintenance.ps1 script to apply drivers
  8. Restart the computer to commit the driver updates

Example

In the below example we have a Dell Optiplex 7040. Looking at Dell’s SCCM driver site, we can determine that we should be expecting at least the following drivers to be updated as part of the maintenance TS.

Arch Category Device Description Previous CAB Current CAB Status
x64 audio Realtek High-Definition Audio Driver ReleaseID: DDG39
DellVersion: A06
VendorVersion:6.0.1.6111
ReleaseID: RT1XX
DellVersion: A07
VendorVersion:6.0.1.6117
Updated
x64 storage Intel Rapid Storage Technology Driver and Management Console ReleaseID: 02RN8
DellVersion: A05
VendorVersion:15.2.10.1044
ReleaseID: CRRKJ
DellVersion: A07
VendorVersion:15.2.15.1058
Updated
x64 video Intel HD, 500, P500 series Graphics Driver ReleaseID: WNF3C
DellVersion: A10
VendorVersion:21.20.16.4590
ReleaseID: TDP4X
DellVersion: A11
VendorVersion:21.20.16.4627
Updated

Driver Package A09 – Source: http://en.community.dell.com/techcenter/enterprise-client/w/wiki/11660.optiplex-7040-windows-10-driver-pack

Intel Storage Driver

 

PowerShell Script Sources

The PowerShell scripts referenced are available on GitHub – https://github.com/SCConfigMgr/ConfigMgr/tree/master/Operating%20System%20Deployment. Here you will also find an optional script for applying a maintenance notice and background (as pictured in the task sequence) – https://github.com/SCConfigMgr/ConfigMgr/blob/master/Operating%20System%20Deployment/Invoke-ITMaintenanceMessage.ps1

Conclusion

Maintaining drivers and BIOS versions can easily be automated with this method. Now set up your task sequences, deploy and keep your environment current.

 

(5859)

Maurice Daly

Maurice has been working in the IT industry since 1999 and was awarded his first MVP Enterprise Mobility award in 2017. Technology focus includes Active Directory, Group Policy, Hyper-V, Windows Deployment (SCCM & MDT) and Office 365.

comments
  • John
    Posted at 03:16 October 18, 2017
    John
    Reply
    Author

    Are the driver packages referenced traditional ConfigMgr driver packages or standard packages used for drivers?

    As always, thank you for your contributions to the community.

  • Jeremy Kowalski
    Posted at 21:26 October 18, 2017
    Jeremy Kowalski
    Reply
    Author

    First, a request. It was really nice back when the Invoke-CMDownloadDriverPackage.ps1 didn’t actually download the driver because then you could use it as an approved/included model detection. It would be great to have a script or parameter to replicate this functionality, either on the legacy Invoke-CMDownloadDriverPackage or the updated version, Invoke-CMApplyDriverPackage. For now, we’re sticking with the NickolajA v1.0.8 for its speed while keeping a task sequence prepped with the SCConfigMgr version for its eventual beneficial deployment.

    Second, some notes regarding shifts and changes between the NickolajA and SCConfigMgr scripts.
    1) The scripts moved from using the model name in the package title to the SKU in the description for its detection. If you have to add new drivers manually, set both the title as well as the description for your packages or they will fail to detect and apply.
    2) If using Windows Servicing\Invoke-CMDownloadDriverPackage v1.1.4: Remove the “Download Driver Package” task, and the “Apply Drivers via DISM” needs to be /Driver:%OSDDriverPackage01% not /Driver:%DriverPackage01%\ as in the step-by-step directions. If you leave the download task in, it will actually download whatever package is defined instead of your drivers. Also as noted above, remove the trailing \ as it’s now included in the variable and will fail when it tried to parse it again. Tested and this worked fine with those changes.
    3) Using the new Drivers\Invoke-CMApplyDriverPackage v1.1.5: Remove both the download and application tasks. It’s all self-contained now.

    Third, thanks. 🙂 Looking forward to when we get to see this working in production.

  • ben
    Posted at 12:15 October 20, 2017
    ben
    Reply
    Author

    Hi Maurice,

    i’m missing two things?
    1. Download BIOS Package
    2. Resume Bitlocker.

    Could i use “Enable Bitlocker” TS Step after the last reboot? or should i use Manage-Bde -Protectors -Enable C:?

    Regards
    ben

    • Maurice Daly
      Posted at 14:54 October 20, 2017
      Maurice Daly
      Reply
      Author

      Hi Ben,

      The download BIOS package is contained within the Invoke-CMDownloadBIOSPackage.ps1 script. In regards to Bitlocker, encryption will automatically resume post full OS restart.

      Maurice

  • Chris
    Posted at 20:09 October 20, 2017
    Chris
    Reply
    Author

    Hello Maurice,

    Your scripts are awesome and I am trying to get it working in my Lenovo environment. I noticed in my task sequence I am getting “PowerShell.exe does not exist at ‘X:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe’ when trying to run the Invoke-CMDownloadBIOSPackage.ps1 script.

    I am trying to replicate your task sequence by running the bios download and install steps right after the Apply Operating System step. I assume this is still in Windows PE? Any idea what my issue is here? I am a bit of a SCCM noob but your scripts and tools are making the upgrade to windows 10 for my fleet a great help! Thank you

    • Ben
      Posted at 08:36 October 21, 2017
      Ben
      Reply
      Author

      Hey Chris,
      I think you are missing Powershell Features in WinPE
      You need to add that to your boot image. Right click on the boot image you use in that TS properties select Powershell Modules and Update Image to Dps.

      • Chris
        Posted at 17:59 October 25, 2017
        Chris
        Reply
        Author

        Thanks for the reply, that sure was it! Now interestingly its able to find the bios in my package list, but I am getting a “You cannot call a method on a null-valued expression error” in my smsts log when running the download package command. Is it possible the %OSDBIOSPackage% variable is incorrect, or do i need to declare it before in my task sequence? I have seen it referenced a few different ways in the scripts here. Or is it possibly some other issue?

        • Maurice Daly
          Posted at 23:07 October 25, 2017
          Maurice Daly
          Reply
          Author

          Hi Chris,

          The variable should be set to %OSDBIOSPackage01% when calling it in the vendor script.

          Maurice

    • Mario
      Posted at 12:18 October 21, 2017
      Mario
      Reply
      Author

      Hi Chris – you’ll need to make sure you have the powershell components added to your boot wim that you’ve assigned to the task sequence.

  • Thomas
    Posted at 10:09 October 25, 2017
    Thomas
    Reply
    Author

    How about a Powershell script that in the same matter that can compare and verify PC_BIOS hardware class, against specific model bios packages available, so one can find which models need to update their bios?

    all this info are in sccm, so it should be doable?

  • Skylar
    Posted at 19:12 November 15, 2017
    Skylar
    Reply
    Author

    So I added this to my In-place Upgrade TS for Windows 10, however it always fails when running the Invoke-CMApplyDriverPackage step. The error is:
    Get-Item : Cannot find drive. A drive with the name ‘C’ does not exist.
    At D:\_SMSTaskSequence\Packages\*packageNameRemoved*\Operating System Deployment\Drivers\Invoke-CMApplyDriverPackage.ps1:374 char:23

    I’ve made sure after upgrading the OS to reboot into WinPE. I’m also confused about why this caused the whole TS to fail as I have “Continue on Failure” checked for that step, but maybe I should apply that to the whole group instead of the individual step.

    So, what can I do about it not being able to find the C: drive? Or can I just not include this in this particular TS? Or because I am laying down a new OS, should I not be using the -OSMaintenance switch?

    Any insight would be appreciated!

  • Suresh
    Posted at 16:45 November 20, 2017
    Suresh
    Reply
    Author

    Hi, I was using dynamic driver update Invoke-CMDownloadDriverPackage.ps1 for staging the driver package for my in-place upgrade from windows 7 to windows 10 1709 and am using “Upgrade Operating System Enterprise” option for the upgrade. Every time it is failing on “GetCMOSImageVersionForTaskSequence” action and it errors out “An error occured while calling ConfigMgr WebService to determine OS Image version. Error message”. Is there a limitation for 1709 OS since it has multiple index.?

  • Jonathan
    Posted at 10:58 November 22, 2017
    Jonathan
    Reply
    Author

    Hello,

    Thank you for your excellent tutorial. However, the system doesn’t seem to install the drivers.

    Invoke-CMDriverMaintenance.ps1 points to a script called Invoke-ITMaintenanceMessage

    https://github.com/SCConfigMgr/ConfigMgr/blob/master/Operating%20System%20Deployment/Drivers/Invoke-CMDriverMaintenance.ps1

    Is this the same version? I don’t see any action to install the drivers in the script specified.

    Thank you in advance!

    Jonathan

    • Maurice Daly
      Posted at 11:35 November 22, 2017
      Maurice Daly
      Reply
      Author

      Hi Jonathan,

      It looks like the contents of that script was mixed up with another. I have just replaced it on GitHub.

      Maurice

  • Keith Morris
    Posted at 20:13 December 7, 2017
    Keith Morris
    Reply
    Author

    I’m in the process of trying to update the BIOS using ConfigMgr WebServices with the Invoke-CMDownloadBIOSPackage.ps1 and the Invoke-LenovoBIOSUpdate.ps1 scripts. I followed the steps in your directions but I keep getting the following error in the smsts.log file. The BIOSPackageDownload.log file is never created.

    Executing command line: Run Powershell script RunPowerShellScript 12/7/2017 1:56:09 PM 1500 (0x05DC)
    C:\_SMSTaskSequence\Packages\GCS0012D\Invoke-CMDownloadBIOSPackage.ps1 : A positional parameter cannot be found that RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)
    accepts argument ‘Update’. RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)
    At line:1 char:1 RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)
    + & ‘C:\_SMSTaskSequence\Packages\GCS0012D\Invoke-CMDownloadBIOSPackage … RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)
    + CategoryInfo : InvalidArgument: (:) [Invoke-CMDownloadBIOSPackage.ps1], ParameterBindingException RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)
    + FullyQualifiedErrorId : PositionalParameterNotFound,Invoke-CMDownloadBIOSPackage.ps1 RunPowerShellScript 12/7/2017 1:56:13 PM 1500 (0x05DC)

    Any help would be appreciated.

    • Nickolaj Andersen
      Posted at 10:46 December 10, 2017
      Nickolaj Andersen
      Reply
      Author

      Hi Keith,

      Could you please share a screen shot together with the command line options set for the Run PowerShell Script step?

      Regards,
      Nickolaj

      • Keith Morris
        Posted at 21:23 December 11, 2017
        Keith Morris
        Reply
        Author
        • Keith Morris
          Posted at 21:25 December 11, 2017
          Keith Morris
          Reply
          Author

          Also, the Modern BIOS Management is a package that contains the Invoke-CMDownloadBIOSPackagd.ps1 and the Invoke-LenovoBIOSUpdate.ps1 PowerShell scripts.

          • Maurice Daly
            Posted at 23:55 December 11, 2017
            Maurice Daly
            Author

            Hi Keith,

            What version of the Invoke-CMDownloadBIOSPackage script are you running?. The current version is 1.0.6.

            Maurice

          • Keith Morris
            Posted at 15:37 December 12, 2017
            Keith Morris
            Author

            I changed the task sequence filter to “BIOS” instead of “BIOS Update” and the scripts are now running. I’ve verified that I’m on version 1.0.6 as well.

            I’m attempting to update the bios on a Lenovo machine but I keep getting this error “wflash2.exe is valid, but is for a machine type other than the current machine”. I believe the script should be using wflash2x64.exe instead of the 32 bit version.

            Looking over the Invoke-LenovoBIOSUpdate.ps1 it appears it’s calling flash.cmd instead of flash64.cmd. Debating on whether to edit the flash.cmd to point to wflash2x64.exe or to edit the Inovke-LenovoBIOSUpdate.ps1 to point to flash64.cmd

    • Jeremy Kowalski
      Posted at 16:17 December 11, 2017
      Jeremy Kowalski
      Reply
      Author

      Also make sure that your filter is “BIOS” not “BIOS Update”, as listed in line 17.

      • Maurice Daly
        Posted at 16:42 December 11, 2017
        Maurice Daly
        Reply
        Author

        Hi Jeremy,

        You can use either in fact. As long as the packages were created by the driver automation tool, their naming structure will be “BIOS Update – %MAKE% %MODEL%”, so using BIOS or BIOS Update as the starting wildcard / matching value is fine.

        Maurice

        • Jeremy Kowalski
          Posted at 18:53 December 11, 2017
          Jeremy Kowalski
          Reply
          Author

          Interesting, as I received the same error as Keith when I tried to do the multiple word filter (BIOS Update) and it was solved by following the directions with the single word.

          It’s possible that the script has been updated to work with pilot updates and in doing so, it’s able to function with the multi-word filter and that Keith is on the same (or a similar) older version without that functionality.

          But I had experienced Keith’s same issue and did not report it as following directions strictly fixed it, making it a failure to read rather than a failure in the code. Our organization has not tried to deploy pilot updates, so I don’t know whether that would have worked or had the same issue.

  • Kevin Schumacher
    Posted at 17:39 January 12, 2018
    Kevin Schumacher
    Reply
    Author

    having an issue where the Invoke-CMDownloadBIOSPackage.ps1 will correctly query BIOS packages, and return a number of packages that match the filter, but then it doesn’t go any further.

    BIOS download package process initiated 1/1/1601 12:00:00 AM 0 (0x0000)
    Manufacturer determined as: Hewlett-Packard 1/1/1601 12:00:00 AM 0 (0x0000)
    Computer model determined as: HP Z440 Workstation 1/1/1601 12:00:00 AM 0 (0x0000)
    Current BIOS version determined as: M60 v02.39 1/1/1601 12:00:00 AM 0 (0x0000)
    Retrieved a total of 11 BIOS packages from web service 1/1/1601 12:00:00 AM 0 (0x0000)
    Setting task sequence variable OSDDownloadDownloadPackages to a blank value 1/1/1601 12:00:00 AM 0 (0x0000)
    Setting task sequence variable OSDDownloadDestinationLocationType to a blank value 1/1/1601 12:00:00 AM 0 (0x0000)
    Setting task sequence variable OSDDownloadDestinationVariable to a blank value 1/1/1601 12:00:00 AM 0 (0x0000)
    Setting task sequence variable OSDDownloadDestinationPath to a blank value 1/1/1601 12:00:00 AM 0 (0x0000)

    • Kevin Schumacher
      Posted at 17:46 January 12, 2018
      Kevin Schumacher
      Reply
      Author

      Web Service 1.3.0
      Invoke-CMDownloadBIOSPackage.ps1 2.0.0

      • Maurice Daly
        Posted at 18:02 January 12, 2018
        Maurice Daly
        Reply
        Author

        Just after spotting this reply. Can you please upgrade to v1.5.0 of the web service and if you could also change the manufacture on the HP BIOS packages to “Hewlett-Packard” as historically “HP” was used.

    • Maurice Daly
      Posted at 18:01 January 12, 2018
      Maurice Daly
      Reply
      Author

      Hi Kevin,

      What version of the Invoke script and web service are you running?.

      Maurice

  • Thomas
    Posted at 14:43 January 15, 2018
    Thomas
    Reply
    Author

    Trying to setup a new TS with all the newest script, i get in DellBIOSUpdate.log that it is unable to locate the flash64w utility..

    its part of the bios package that is downloadeed with the driver automation tool, so uncertain where the fault lies?

    • Maurice Daly
      Posted at 15:23 January 15, 2018
      Maurice Daly
      Reply
      Author

      Hi Thomas,

      If you look in the log you will see an entry to confirm that the Flash64w utility has been downloaded. You can also check this in the repository path you specified. Assuming that there have been no issues downloading and extracting the exe from the zip file containing the Flash64w, then I suggest you use content explorer to ensure that your DP has both files in the package.

      Maurice

      • Thomas
        Posted at 09:56 January 16, 2018
        Thomas
        Reply
        Author

        The file has been downloaded, together with the correct bios file, it sets the package with a custom variable of OSDBIOSPacakge01. It when running the invoke-DELLBIOSUpdate script it fails with incorrect function, as if the file itself is missing, or looking at the wrong place.

        I have verified that the TS has the -Path “%OSDBIOSPackage01%” in itself. Running v1.05 of the Dell BIOSUupdate script.

        smsts.log shows the following:
        Resolved source to ‘C:\_SMSTaskSequence\Packages\UMV00295’
        Command line for extension .exe is “%1” %*
        Set command line: Run Powershell script
        Working dir ‘C:\_SMSTaskSequence\Packages\UMV00295’
        Executing command line: Run Powershell script
        Process completed with exit code 1
        Command line returned 1

        • Maurice Daly
          Posted at 10:04 January 16, 2018
          Maurice Daly
          Reply
          Author

          What does the contents of the Invoke-DellBIOSUpdate log file look like?

          • Thomas
            Posted at 10:08 January 16, 2018
            Thomas
            Author

            3 Simple lines.

            Initiating script to determine flashing capabilities for Dell BIOS updates
            Attempting to use flash utility:
            Unable to locate the Flash64W.exe utility

            The funny thing, is that it did actually update it aswell this last time, for unknown reasons.

          • Maurice Daly
            Posted at 10:11 January 16, 2018
            Maurice Daly
            Author

            Can you drop me a mail with a screenshot of the Run PowerShell step used for the Invoke-DellBIOSUpdate?

  • Bruce
    Posted at 22:25 February 8, 2018
    Bruce
    Reply
    Author

    Maurice,

    Can the Bios and Drivers be updated outside of WinPE? I’m trying to update Bios and Drivers on computers that are on VPN and they would have to do everything within it’s session and reboot just to finish installing the bios.

    • Maurice Daly
      Posted at 23:12 February 9, 2018
      Maurice Daly
      Reply
      Author

      Hi Bruce,

      The BIOS and Drivers can indeed be updated outside of WinPE. If you view the solutions pages you will see the switches for running the updates in the Full OS.

      Maurice

  • Dean Buen
    Posted at 20:58 February 9, 2018
    Dean Buen
    Reply
    Author

    With the latest “Invoke-CMApplyDriverPackage” Powershell script (version 2.0.5), what is the task sequence restart process look like when applying updates to an existing FullOS; using the -DeploymentType DriverUpdate command?

    Do we still need to reboot the host computer into WinPE? and then run the “Invoke-CMApplyDriverPackag.ps1” -DeploymentType DriverUpdate?

    Thanks,
    Dean

    • Maurice Daly
      Posted at 23:15 February 9, 2018
      Maurice Daly
      Reply
      Author

      Hi Dean,

      The process is to simply call the script in a task sequence with the DeploymentType set to DriverUpdate. The script will then download the drivers and use the PNPutil command to update the drivers. There is no need to reboot into WinPE using this method.

      Maurice

  • Leave a Reply