This is the third version of the script solution; it is very simple. You detect make/model in any way you would like to, create a rule based on BIOS version, if the rule match, nothing happens, otherwise it runs any command you want. That said, you could use this for other task as well. Most common question is “does it work with any Make/Model”`No, there are some vendors that does not provide the ability to run a BIOS upgrade silently without reboot without control, that is, the darn thing reboots immediately and that usually breaks the Task Sequence. I have one thing for those vendors to say “Shame on you!”
here are older posts on the subject
Detect the Model
The detection in the script is actually whatever you want, it is just a “If-then” here are two sample lines detection that you will find in the script
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP EliteBook 8560w'){} if($ModelAlias -eq 'HP EliteBook 8460p'){}
Use the detection method for each model you like, very simple
Detect the BIOS version
This is also not that hard, here are 2 sample lines from the script
if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCF Ver. F.63'){} if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '786G1 v01.27'){}
Store the upgrade files
The upgrade files are stored with the model name, like this:
The Silent Command
You also need to figure out the command, not really hard, download the bios upgrade, read how to run it from a command line, update the script and you are done, here is a sample of one of those sections.
$Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p" $Executable = $Location + "\" + $exe Set-Location -Path $Location Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCE.CAB" –Verbose
Run the script
in MDT you can import the folder with the script as a application and set this as the command line:
PowerShell.exe -ExecutionPolicy Bypass -File Install-BIOSUpgrade.ps1
In ConfigMgr you can import this as a Package and then run the command line the same way
It is also possible to run this outside of a task sequence if you like, it works as a stand alone script, however, you cannot use the integration with MDT of course.
If you want it is possible to add a custom property in customsettings.ini, something like “NeedReboot”, then you can add the following to happen if the BIOS has been upgraded
$tsenv.Value(“NeedReboot”) = “YES”
If you then in the step after this, set a condition on a reboot step, well then it will reboot when needed, otherwise not, you can read about that in one of my old postings here
The result
The Script
Function Import-SMSTSENV{ try { $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment Write-Output "$ScriptName - tsenv is $tsenv " $MDTIntegration = "YES" #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" } } catch { Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment" Write-Output "$ScriptName - Running in standalonemode" $MDTIntegration = "NO" } Finally { if ($MDTIntegration -eq "YES"){ $Logpath = $tsenv.Value("LogPath") $LogFile = $Logpath + "\" + "$ScriptName.log" } Else{ $Logpath = $env:TEMP $LogFile = $Logpath + "\" + "$ScriptName.log" } } } Function Start-Logging{ start-transcript -path $LogFile -Force } Function Stop-Logging{ Stop-Transcript } Function Invoke-Exe{ [CmdletBinding(SupportsShouldProcess=$true)] param( [parameter(mandatory=$true,position=0)] [ValidateNotNullOrEmpty()] [string] $Executable, [parameter(mandatory=$false,position=1)] [string] $Arguments ) if($Arguments -eq "") { Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru" $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru }else{ Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru" $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru } Write-Verbose "Returncode is $($ReturnFromEXE.ExitCode)" Return $ReturnFromEXE.ExitCode } # Set vars $SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path $SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path $SOURCEROOT = "$SCRIPTDIR\Source" $SettingsFile = $SCRIPTDIR + "\" + $SettingsName $LANG = (Get-Culture).Name $OSV = $Null $ARCHITECTURE = $env:PROCESSOR_ARCHITECTURE #Try to Import SMSTSEnv . Import-SMSTSENV # Set more vars $Make = $tsenv.Value("Make") $Model = $tsenv.Value("Model") $ModelAlias = $tsenv.Value("ModelAlias") $MakeAlias = $tsenv.Value("MakeAlias") #Start Transcript Logging . Start-Logging #Output base info Write-Output "" Write-Output "$ScriptName - ScriptDir: $ScriptDir" Write-Output "$ScriptName - SourceRoot: $SOURCEROOT" Write-Output "$ScriptName - ScriptName: $ScriptName" Write-Output "$ScriptName - Current Culture: $LANG" Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration" Write-Output "$ScriptName - Log: $LogFile" Write-Output "$ScriptName - Model (win32_computersystem): $((Get-WmiObject Win32_ComputerSystem).model)" Write-Output "$ScriptName - Name (Win32_ComputerSystemProduct): $((Get-WmiObject Win32_ComputerSystemProduct).Name)" Write-Output "$ScriptName - Version (Win32_ComputerSystemProduct): $((Get-WmiObject Win32_ComputerSystemProduct).Version)" Write-Output "$ScriptName - Model (from TSENV): $Model" Write-Output "$ScriptName - ModelAlias (from TSENV): $ModelAlias" #Check Model if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP EliteBook 8560w'){ Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)" Write-Output "Checking BIOS Version" Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)" if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SVD Ver. F.50'){ Write-Output "Needs upgrade" $Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP EliteBook 8560w" $Executable = $Location + "\" + $exe Set-Location -Path $Location Invoke-Exe -Executable "$Executable" -Arguments "/s /p LCadmin1.bin" -Verbose } else { Write-Output "No Need to upgrade" } } if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP ProBook 6570b'){ Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)" Write-Output "Checking BIOS Version" Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)" if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*ICE*'){ if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68ICE Ver. F.62'){ Write-Output "Needs upgrade" $Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP ProBook 6570b" $Executable = $Location + "\" + $exe Set-Location -Path $Location Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68ICE.cab" -Verbose } else { Write-Output "No Need to upgrade" } } if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*ICF*'){ if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68ICF Ver. F.62'){ Write-Output "Needs upgrade" $Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP ProBook 6570b" $Executable = $Location + "\" + $exe Set-Location -Path $Location Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68ICF.cab" -Verbose } else { Write-Output "No Need to upgrade" } } } if($ModelAlias -eq 'HP EliteBook 8460p'){ Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)" Write-Output "Checking BIOS Version" Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)" if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*SCF*'){ if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCF Ver. F.63'){ Write-Output "Needs upgrade" $Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p" $Executable = $Location + "\" + $exe Set-Location -Path $Location Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCF.CAB" -Verbose } else { Write-Output "No Need to upgrade" } } if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*SCE*'){ if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCE Ver. F.63'){ Write-Output "Needs upgrade" $Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p" $Executable = $Location + "\" + $exe Set-Location -Path $Location Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCE.CAB" -Verbose } else { Write-Output "No Need to upgrade" } } } if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP Compaq dc7900 Small Form Factor'){ Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)" Write-Output "Checking BIOS Version" Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)" if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '786G1 v01.27'){ Write-Output "Needs upgrade" $Exe = 'hpqflash.exe' $Location = "$SCRIPTDIR\Source\HP Compaq dc7900 Small Form Factor\HPQFlash" $Executable = $Location + "\" + $exe $SourceFile = $Location + "\" + "Password01.bin" $Destination = $env:TEMP $DestinationFile = $Destination + "\" + "Password01.bin" Copy-Item -Path $SourceFile -Destination $DestinationFile -Force -Verbose Set-Location -Path $Location Invoke-Exe -Executable $Executable -Arguments "/s /p $DestinationFile" } else { Write-Output "No Need to upgrade" } } #Stop Logging . Stop-Logging
/mike
Categories: BIOS, ConfigMgr, MDT, OS Deployment, OSD, PowerShell
Great work. Only issue I see here is that it still leaves open the issue of an Encrypted system being bricked. I’ve posted my own solution to this which automatically unlocks a drive (BitLocker only but could be extended to other solutions) before upgrading the BIOS. https://deploymentramblings.wordpress.com/2013/05/29/sccm-2012-deploying-dell-bios-updates-using-the-application-model/
Great, it also depends on how “hard” the PCR settings are in AD! Great job!
Thank for for this! I have been using version 2 of this script for a long time now and it works great.
Just out of curiosity. What is new/changed/improved in this version of the script compared to version 2?
Thanks you for posting this. Really helped with our companies upgrade.
We did however alter it a bit so that it’s expandable and shrinkable:
#Start
#Get vendor
$Vendor = (get-wmiobject win32_computersystem).manufacturer
$Bios = (Get-WmiObject Win32_bios).smbiosbiosversion
if ($Vendor -eq “Dell Inc.”) {
$Model = (Get-WmiObject Win32_ComputerSystemProduct).Name
$ModelPath = $PSScriptRoot + “\source\” + $Model
$ModelCorrect = Test-Path $ModelPath
}
elseif ($Vendor -eq “LENOVO”) {
$Model = (Get-WmiObject Win32_ComputerSystemProduct).Version
$ModelPath = $PSScriptRoot + “\source\” + $Model
$ModelCorrect = Test-Path $ModelPath
}
if ($ModelCorrect -eq $True) {
$BiosVer = Get-Content ($ModelPath + “\Version.txt”)
Write-Output “$ScriptName – Upgrading BIOS version to = $BiosVer”
$BiosCheck =($BiosVer -eq $Bios)
if ($BiosCheck -eq $False) {
if ($MDTIntegration -eq “YES”){
$tsenv.Value(“NeedReboot”) = “YES”
$RestartNeeded = 1
}
$Exe = ‘update.cmd’
$Location = $ModelPath
$Executable = $Location + “\” + $exe
Set-Location -Path $Location
Invoke-Exe -Executable “$Executable” -Verbose
}
else {
write-output “This machine does not require a Bios Update”
}
}
This way, if you have a predefined file structure that follows some simple standards, you can just add and remove hardware entities in your folder structure and the script will autodetect the correct BIOS.
I excluded the unchanged parts of the script, as well as the part were we force every computer which is updated to restart after 3 minutes
Note: I am really NOT very good at scripting , especially in powershell, so this stuff could probably be done in a much smarter way. Jsut wanted to share our take on it