MSEndpointMgr

Manage HP Bios Updates with Proactive Remediations – Part 1

We have been working for a while with getting together a solution that combines Modern Bios Management and Modern Driver Management with Proactive Remediations in Microsoft Intune. This would allow full Bios and Driver managements of your Intune managed devices like you are used to with Configuration Manager today. This post, which is part 1, is about how to get the requirements in place.

The requirements for managing Bios and Drivers in the cloud from the driver automation tool is to have an up to date version of PowerShellGet, PackageManagement and HP’s HPCMSL module.

Proactive Remediations

To get all the requirements in place we have created a Proactive Remediatons Script package that detects whether or not your HP Clients is up to date on the modules, and update them when needed. The scripts can be downloaded from here: GitHub

Detection Script

The detections script:

# HP HPCMLS Detection Script 
# Created by: 
# Jan Ketil Skanke & Maurice Daly 
# MSEndpointMgr.com 

# Start Detection
# Validate that script is executed on HP hardware
$Manufacturer = (Get-WmiObject -Class "Win32_ComputerSystem" | Select-Object -ExpandProperty Manufacturer).Trim()
switch -Wildcard ($Manufacturer) {
    "*HP*" {
        Write-output "Validated HP hardware check" 
    }
    "*Hewlett-Packard*" {
        Write-output "Validated HP hardware check" 
    }
    default {
        Write-output "Not running on HP Hardware, Remediation not applicable"; exit 0
    }
}
$ProviderInstalled = $false
$Providers = Get-PackageProvider -ListAvailable 
if ($Providers.Name -notcontains "NuGet") {
    Write-Output "Required provider missing"; exit 1
}elseif (((Get-PackageProvider -Name "NuGet").version) -le ([Version]"2.8.5")) {
    Write-Output "Provider must be updated"; exit 1
}else {
    Write-Output "Provider OK, Checking for modules" 
    $ProviderInstalled = $true
}

if ($ProviderInstalled) {
    $PowerShellGetInstalledModule = Get-InstalledModule -Name "PowerShellGet" -ErrorAction SilentlyContinue -Verbose:$false
    if ($PowerShellGetInstalledModule -ne $null) {
        try {
            # Attempt to locate the latest available version of the PowerShellGet module from repository
            Write-Output "Attempting to request the latest PowerShellGet module version from repository" 
            $PowerShellGetLatestModule = Find-Module -Name "PowerShellGet" -ErrorAction Stop -Verbose:$false
            if ($PowerShellGetLatestModule -ne $null) {
                if ($PowerShellGetInstalledModule.Version -lt $PowerShellGetLatestModule.Version) {
                    Write-Output "Newer PowerShellGet version detected, update from repository is needed";exit 1
                } else {
                    Write-Output "PowershellGet is Ready"
                    $HPInstalledModule = Get-InstalledModule | Where-Object {$_.Name -match "HPCMSL"} -ErrorAction SilentlyContinue -Verbose:$false
                    if ($HPInstalledModule -ne $null) {
                        $HPGetLatestModule = Find-Module -Name "HPCMSL" -ErrorAction Stop -Verbose:$false
                        if ($HPInstalledModule.Version -lt $HPGetLatestModule.Version) {
                            Write-Output "Newer HPCMSL version detected, update from repository is needed";exit 1
                        } else {
                            Write-Output "HPCMSL Module is up to date"; exit 0
                        }
                    } else {
                        Write-Output "HPCMSL Module is missing"; exit 1
                    }
                }
            } else {
                Write-Output "Location request for the latest available version of the PowerShellGet module failed, can't continue"; exit 1
            }
        }
        catch [System.Exception] {
            Write-Output "Failed to retrieve the latest available version of the PowerShellGet module, can't continue. Error message: $($_.Exception.Message)" ; exit 1
        }
    } else {
        Write-Output "PowershellGet module is missing"; exit 1
    }
}

In Procative Remediations the Detect script should only do just that. This detection script checks for all prerequisites and the HPCMLS module it self. Verifies if it is on the latest version and Exit 1 if everything is not up to date. If everything looks good, we do a Exit 0. Only runs with Exit 1 will trigger the remediation script to run.

Remediation script

# HP HPCMLS Detection Script 
# Created by: 
# Jan Ketil Skanke & Maurice Daly 
# MSEndpointMgr.com 
# Start-PowerShellSysNative is inspired by @NickolajA's method to install the HPCMLS module 

#Start remediate
#This remediation must run in system context and in 64bit powershell. 
function Start-PowerShellSysNative {
    param (
        [parameter(Mandatory = $false, HelpMessage = "Specify arguments that will be passed to the sysnative PowerShell process.")]
        [ValidateNotNull()]
        [string]$Arguments
    )

    # Get the sysnative path for powershell.exe
    $SysNativePowerShell = Join-Path -Path ($PSHOME.ToLower().Replace("syswow64", "sysnative")) -ChildPath "powershell.exe"

    # Construct new ProcessStartInfo object to run scriptblock in fresh process
    $ProcessStartInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo
    $ProcessStartInfo.FileName = $SysNativePowerShell
    $ProcessStartInfo.Arguments = $Arguments
    $ProcessStartInfo.RedirectStandardOutput = $true
    $ProcessStartInfo.RedirectStandardError = $true
    $ProcessStartInfo.UseShellExecute = $false
    $ProcessStartInfo.WindowStyle = "Hidden"
    $ProcessStartInfo.CreateNoWindow = $true

    # Instatiate the new 64-bit process
    $Process = [System.Diagnostics.Process]::Start($ProcessStartInfo)

    # Read standard error output to determine if the 64-bit script process somehow failed
    $ErrorOutput = $Process.StandardError.ReadToEnd()
    if ($ErrorOutput) {
        Write-Error -Message $ErrorOutput
    }
}#endfunction

 # Enable TLS 1.2 support for downloading modules from PSGallery (Required)
 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Validate that script is executed on HP hardware
$Manufacturer = (Get-WmiObject -Class "Win32_ComputerSystem" | Select-Object -ExpandProperty Manufacturer).Trim()
switch -Wildcard ($Manufacturer) {
    "*HP*" {
        Write-output "Validated HP hardware check" 
    }
    "*Hewlett-Packard*" {
        Write-output "Validated HP hardware check" 
    }
    default {
        Write-output "Not running on HP Hardware, Script not applicable"; exit 0
    }
}

# Install latest NuGet package provider
try {
Write-Output "Attempting to install latest NuGet package provider"
$PackageProvider = Install-PackageProvider -Name "NuGet" -Force -ErrorAction Stop -Verbose:$false
}
catch [System.Exception] {
    Write-output "Unable to install latest NuGet package provider. Error message: $($_.Exception.Message)"; exit 1
}   

# Install the latest PowershellGet Module 
if ($PackageProvider.Version -ge "2.8.5"){
    $PowerShellGetInstalledModule = Get-InstalledModule -Name "PowerShellGet" -ErrorAction SilentlyContinue -Verbose:$false
    if ($PowerShellGetInstalledModule -ne $null) {
        try {
            # Attempt to locate the latest available version of the PowerShellGet module from repository
            Write-Output "Attempting to request the latest PowerShellGet module version from repository" 
            $PowerShellGetLatestModule = Find-Module -Name "PowerShellGet" -ErrorAction Stop -Verbose:$false
            if ($PowerShellGetLatestModule -ne $null) {
                if ($PowerShellGetInstalledModule.Version -lt $PowerShellGetLatestModule.Version) {
                    try {
                        # Newer module detected, attempt to update
                        Write-Output "Newer version detected, attempting to update the PowerShellGet module from repository" 
                        Update-Module -Name "PowerShellGet" -Scope "AllUsers" -Force -ErrorAction Stop -Confirm:$false -Verbose:$false
                    }
                    catch [System.Exception] {
                        Write-Output "Failed to update the PowerShellGet module. Error message: $($_.Exception.Message)"; exit 1
                    }
                }
            }
            else {
                Write-Output "Location request for the latest available version of the PowerShellGet module failed, can't continue"; exit 1
            }
        }
        catch [System.Exception] {
            Write-Output "Failed to retrieve the latest available version of the PowerShellGet module, can't continue. Error message: $($_.Exception.Message)" ; exit 1
        }
    } else {
        try {
            # PowerShellGet module was not found, attempt to install from repository
            Write-Output "PowerShellGet module was not found, attempting to install it including dependencies from repository" 
            Write-Output "Attempting to install PackageManagement module from repository" 
            Install-Module -Name "PackageManagement" -Force -Scope AllUsers -AllowClobber -ErrorAction Stop -Verbose:$false
            Write-Output "Attempting to install PowerShellGet module from repository" 
            Install-Module -Name "PowerShellGet" -Force -Scope AllUsers -AllowClobber -ErrorAction Stop -Verbose:$false
        }
        catch [System.Exception] {
            Write-Output "Unable to install PowerShellGet module from repository. Error message: $($_.Exception.Message)"; exit 1
        }
    }
    
    #Install the latest HPCMSL Module
    $HPInstalledModule = Get-InstalledModule | Where-Object {$_.Name -match "HPCMSL"} -ErrorAction SilentlyContinue -Verbose:$false
    if ($HPInstalledModule -ne $null) {
        $HPGetLatestModule = Find-Module -Name "HPCMSL" -ErrorAction Stop -Verbose:$false
        if ($HPInstalledModule.Version -lt $HPGetLatestModule.Version) {
            Write-Output "Newer HPCMSL version detected, updating from repository"
            $scriptBlock = {
                try {
                    # Install HP Client Management Script Library
                    Write-Output -Value "Attempting to install HPCMSL module from repository" 
                    Update-Module -Name "HPCMSL" -AcceptLicense -Force -ErrorAction Stop -Verbose:$false
                } 
                catch [System.Exception] {
                    Write-OutPut -Value "Unable to install HPCMSL module from repository. Error message: $($_.Exception.Message)"; exit 1
                }
            } 
            Start-PowerShellSysNative -Arguments "-ExecutionPolicy Bypass $($scriptBlock)"
        } else {
            Write-Output "HPCMSL Module is up to date"; exit 0
        }
    } else {
        Write-Output "HPCMSL Module is missing, try to install from repository"
        $scriptBlock = {
            try {
                # Install HP Client Management Script Library
                Write-Output -Value "Attempting to install HPCMSL module from repository" 
                Install-Module -Name "HPCMSL" -AcceptLicense -Force -ErrorAction Stop -Verbose:$false
            } 
            catch [System.Exception] {
                Write-OutPut -Value "Unable to install HPCMSL module from repository. Error message: $($_.Exception.Message)"; exit 1
            }
        } 
        Start-PowerShellSysNative -Arguments "-ExecutionPolicy Bypass $($scriptBlock)"
    }
}

The remediation script will check for the latest version of the required PowerShell modules and the Package Provider. As we need features in the latest version of the modules we are running the HPCMLS module remediation as a scriptBlock in a new process. This makes sure that the installation of the HPCMSL module runs in a fresh process where all the newest modules and features are available. Without that it would most likely fail to install because the required -AcceptLicense parameter would not be available.

Setup the Proactive Remediation

Even though we check for HP Hardware in our scripts, we would suggest a Azure AD Dynamic group for targeting that contains only your HP clients. That group rule could look like this:
(device.deviceManufacturer -contains "HP") or (device.deviceManufacturer -contains "Hewlett-Packard")

With the targeting group in place, go to https://endpoint.microsoft.com – Reports – Endpoint Analytics – Proactive Remediations. Click on Create script package.

Give the package a name and click on Next

Get the scripts from Github here: (HPCMLS Remediation Scripts) and upload them in this page.
IMPORTANT: Choose run in 64-bit powershell or the script will have some issues

Assign the remediation script package to your dynamic Azure AD group. I have chosen to run this daily, but this can be changed by clicking on the 3 dots in the end of the line after assigning to a group.

Click Next and then Click on Create on the Review + Create page if everything looks OK.

Monitoring

Now that the remediation is set to run every day, we can follow that status on all of our devices over time . We can see when an update has occured by looking at the number of devices with Reccured (means the remediation has runned), Issue fixed tells us the detection run after remediation (Post-remediation detection) has succesfully detected that issue is fixed. Without issues tells us how many devices that are up to date.

Next step

With this first remediation we have put all the requirements in place for upcoming features in Modern Bios and Driver management to utilize Proactive Remediations to maintain drivers and bios versions over time. Stay tuned for Part 2 coming soon.

Jan Ketil Skanke

Jan Ketil is an Enterprise Mobility MVP since 2016 and are working as a COO and Principal Cloud Architect at CloudWay in Norway. He has been in the industry for more than 20 years working for both Microsoft Partners and Microsoft. He loves to speak about anything around Enterprise Mobility and Secure Productivity. He is also the lead for the community conference Experts Live Norway. Jan Ketil has presented at large industry conferences like Microsoft Ignite, Microsoft Ignite The Tour, Microsoft Inspire, Experts Live Europe, Techmentor HQ (3rd best session 2019) and NIC Conference in Oslo.

Maurice Daly

Maurice has been working in the IT industry for the past 20 years and currently working in the role of Senior Cloud Architect with CloudWay. With a focus on OS deployment through SCCM/MDT, group policies, active directory, virtualisation and office 365, Maurice has been a Windows Server MCSE since 2008 and was awarded Enterprise Mobility MVP in March 2017. Most recently his focus has been on automation of deployment tasks, creating and sharing PowerShell scripts and other content to help others streamline their deployment processes.

8 comments

Sponsors

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.