Automating Dell BIOS Upgrades with PowerShell in an Enterprise Environment
Managing BIOS updates across enterprise devices is often a complex and high-risk task. Firmware updates require careful coordination, user awareness, and strict safeguards such as power checks and version validation. This PowerShell solution addresses those challenges by delivering a fully automated, user-aware BIOS upgrade workflow integrated with Microsoft Configuration Manager (SCCM) task sequences.
This script combines automation, user interaction, validation logic, and a graphical interface to create a reliable and controlled BIOS upgrade process.
Overview of the Solution
The script is designed to handle the entire BIOS upgrade lifecycle, from initial detection to final verification. It performs the following key functions:
- Detects system model and current BIOS version
- Compares it against a predefined expected version (via JSON file)
- Determines whether an upgrade is required
- Prompts the user with retry options
- Enforces AC power requirements for laptops
- Executes the BIOS update silently
- Displays a real-time progress UI
- Logs all actions for auditing
- Verifies success after reboot
This approach ensures both operational efficiency and user safety.
Dynamic BIOS File Handling
The script automatically identifies the BIOS executable located in the same directory. This avoids hardcoding file names and allows the same script package to support multiple models.
By dynamically picking the executable, administrators can easily maintain the solution by simply updating the BIOS files in the folder.
Logging and Traceability
A structured logging mechanism writes all activity to:
C:\ProgramData\GlobalClient\LogFiles
Each device generates a uniquely named log file based on its model. This makes troubleshooting straightforward and ensures full traceability for every upgrade attempt.
User-Friendly Progress Interface
A key highlight of this solution is its custom WPF-based graphical interface. Instead of leaving users unsure about what’s happening, the script displays:
- A progress bar with percentage completion
- Status messages indicating current steps
- A scrolling output log
- Corporate branding through logo integration
The UI also includes basic window controls like minimize functionality and drag movement, offering a polished and professional experience.
Integration with SCCM Task Sequences
The script leverages the Microsoft.SMS.TSEnvironment COM object to interact with task sequence variables. This allows seamless communication between different stages of deployment.
Key variables include:
- BIOS upgrade requirement status
- User response (approve/postpone)
- Upgrade result (success/failure)
- BIOS password for secure flashing
This integration ensures the script fits naturally into enterprise deployment workflows.
BIOS Version Validation Using JSON
Expected BIOS versions are stored externally in a JSON file. The script reads this file and matches the device model to determine the correct BIOS version.
It supports both:
- Exact model matching
- Partial matching for flexibility
By separating configuration from logic, this design makes it easy to maintain and scale.
Controlled User Interaction
Before initiating the upgrade, the script prompts the user with a clear message explaining the process and its impact.
Users can:
- Proceed with the upgrade
- Postpone it up to five times
A registry-based counter tracks postponements. Once the limit is reached, the upgrade becomes mandatory. This ensures that critical updates are not indefinitely delayed while still giving users flexibility.
AC Power Enforcement
BIOS updates must not be interrupted, especially on laptops. The script detects whether the system is a laptop based on chassis type and checks battery status.
If the device is not plugged into AC power:
- The user is prompted to connect the charger
- The script waits until AC power is confirmed
Desktops automatically bypass this check.
Silent and Controlled BIOS Execution
The BIOS update is launched silently with predefined arguments to enforce behavior such as:
- No user interaction
- Forced update if required
- Logging to a file
- Password authentication
The script monitors the process and simulates progress in the UI until completion.
Post-Upgrade Validation
After the system restarts, the script verifies whether the BIOS update was successful by comparing the installed version with the expected version.
It also handles user session behavior by:
- Waiting for user login if necessary
- Proceeding after a defined timeout
If the upgrade succeeds:
- Status is updated in task sequence variables
- Retry counters are cleared
If it fails:
- Failure status is recorded for further action
Final User Notifications
The script provides clear feedback through popup messages:
- Success notification indicating completion and reboot timing
- Failure notification showing the error code
This improves transparency and helps reduce support requests.
End-to-End Workflow
Check Phase
Determines whether a BIOS upgrade is neededPrompt Phase
Interacts with the user and manages postponement logicExecution Phase
Runs the BIOS upgrade with a live progress UIPost-Validation Phase
Confirms upgrade success after rebootUser Notification Phase
Displays final outcome
Benefits of the Approach
This solution provides several advantages:
- Reliability: Built-in checks reduce the risk of failed updates
- User Awareness: Clear prompts and UI improve transparency
- Compliance: Retry limits enforce completion of critical updates
- Scalability: JSON-driven configuration simplifies management
- Integration: Seamlessly works within SCCM task sequences
Conclusion
BIOS updates are often seen as disruptive and risky, but with the right automation strategy, they can become predictable and manageable.
This PowerShell-based solution transforms BIOS upgrades into a structured, user-aware, and enterprise-ready process. By combining validation, automation, and user interaction, it ensures updates are applied safely while maintaining a positive user experience.
It demonstrates how thoughtful scripting can turn a traditionally complex task into a streamlined and controlled operation at scale.
I am attaching the sample code here:
param (
[ValidateSet("Prompt", "PostTSRun", "SuccessPopup", "FailedPopup", "CheckOnly")]
[string]$Action = "CheckOnly"
)
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms
$ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$LogPath = "C:\ProgramData\LogFiles"
$Model = (Get-WmiObject Win32_ComputerSystem).Model
$LogFile = Join-Path $LogPath ("BIOS_Upgrade_{0}.log" -f ($Model -replace '[\\/:*?"<>|]','_'))
function Write-Log {
param([string]$Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp - $Message" | Out-File -Append -FilePath $LogFile -Encoding ascii
}
function Run-CheckOnly {
Write-Log "===== BIOS UPGRADE MAIN SCRIPT STARTED ====="
Write-Log "===== Running $Action Action ====="
$tsEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$Model = (Get-WmiObject Win32_ComputerSystem).Model.Trim()
$Actual = (Get-CimInstance Win32_BIOS).SMBIOSBIOSVersion.Trim()
$Expected = Get-ExpectedBiosVersion
Write-Log "Model: $Model"
Write-Log "Actual BIOS: $Actual"
Write-Log "Expected BIOS: $Expected"
# Default = No upgrade
$UpgradeRequired = "FALSE"
$UserLogged = (quser 2>$null) | Where-Object { $_ -notmatch "USERNAME" }
if (-not $UserLogged) {
Write-Log "No user logged in."
Try{ $tsEnv.Value("UserLogged") = "No"
}
catch{}
return
}
Write-Log "User session detected."
Try{ $tsEnv.Value("UserLogged") = "Yes"
}
catch{}
# ---------------- AC POWER CHECK ----------------
Write-Log "Checking AC power status..."
$ChassisTypes = (Get-CimInstance Win32_SystemEnclosure -ErrorAction SilentlyContinue).ChassisTypes
$LaptopChassis = @(8,9,10,14,30,31,32)
$IsLaptop = $false
if ($ChassisTypes | Where-Object { $_ -in $LaptopChassis }) {
$IsLaptop = $true
}
if (-not $IsLaptop) {
Write-Log "Desktop detected (Chassis: $($ChassisTypes -join ',')). Skipping AC check."
$tsEnv.Value("ACPower") = "Yes"
}
else {
$Battery = Get-CimInstance Win32_Battery -ErrorAction SilentlyContinue
if ($Battery -and $Battery.BatteryStatus -eq 2) {
Write-Log "Laptop is connected to AC power."
Try{$tsEnv.Value("ACPower") = "Yes"
}
catch{}
}
else {
Write-Log "Laptop is NOT connected to AC power."
Try{$tsEnv.Value("ACPower") = "No"
}
catch{}
}
}
Set-ModelAndUpgradeStatus
Write-Log "CheckOnly action complete."
exit 0
}
function Wait-ForACPower {
Write-log "Checking AC power status..."
$Chassis = (Get-CimInstance Win32_SystemEnclosure).ChassisTypes
$LaptopChassis = @(8,9,10,14,30,31,32)
if (-not ($Chassis | Where-Object { $_ -in $LaptopChassis })) {
Write-Log "Device chassis type = $($Chassis -join ',') → DESKTOP detected. Skipping AC power check."
return
}
Write-Log "Laptop detected (ChassisType = $($Chassis -join ',')). Enforcing AC adapter requirement."
while ($true) {
try {
$Batt = (Get-CimInstance Win32_Battery).BatteryStatus
}
catch {
# Battery missing? treat as AC OK (rare case)
Write-log "Battery info not available; assuming AC power."
return
}
# BatteryStatus = 2 means AC connected
if ($Batt -eq 2) {
Write-log "System on AC power."
return
}
Write-log "AC NOT connected. Prompting user..."
[System.Windows.MessageBox]::Show(
"Please connect your AC Power Adapter to continue the BIOS upgrade.",
"AC Power Required",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Warning
)
Start-Sleep -Seconds 3
}
}
function Get-ExpectedBiosVersion {
$JsonFile = Join-Path $ScriptPath "BiosVersions.json"
if (!(Test-Path $JsonFile)) {
Write-Log "ERROR: JSON file missing at $JsonFile"
return $null
}
try {
$Table = Get-Content $JsonFile | ConvertFrom-Json
}
catch {
Write-Log "ERROR: Unable to parse JSON file!"
return $null
}
# Exact match
if ($Table.$Model) {
return $Table.$Model
}
# Partial match
foreach ($key in $Table.PSObject.Properties.Name) {
if ($Model -like "*$key*") {
Write-Log "Partial match found: $key => $($Table.$key)"
return $Table.$key
}
}
Write-Log "ERROR: No BIOS version entry found for this model"
return $null
}
function Set-ModelAndUpgradeStatus {
Write-Log "Evaluating model and BIOS upgrade requirement..."
$tsEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$Model = (Get-WmiObject Win32_ComputerSystem).Model
$Actual = (Get-CimInstance Win32_BIOS).SMBIOSBIOSVersion.Trim()
$Expected = Get-ExpectedBiosVersion
$UpgradeRequired = "FALSE"
if ($Expected) {
if ($Actual.ToLower() -ne $Expected.ToLower()) {
$UpgradeRequired = "TRUE"
Write-Log "BIOS upgrade required = TRUE"
}
else {
$UpgradeRequired = "FALSE"
Write-Log "BIOS upgrade required = FALSE"
}
} else {
Write-Log "Expected BIOS not found → cannot determine upgrade requirement"
}
try {
$tsEnv.Value("MachineModel") = $Model
$tsEnv.Value("BIOSUpgradeRequired") = $UpgradeRequired
Write-Log "TS Vars Set: MachineModel=$Model , BIOSUpgradeRequired=$UpgradeRequired"
}
catch {
Write-Log "ERROR: Could not write TS variables..."
}
}
function Show-BIOSUpgradetPrompt {
Write-Log "===== Running $Action Action ====="
$tsEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
# ALWAYS set model + upgrade required for TS
Set-ModelAndUpgradeStatus
# Load expected BIOS version
$Expected = Get-ExpectedBiosVersion
if (!$Expected) {
Write-Log "Cannot continue without expected BIOS version."
exit 0
}
# Write expected version to TS
try {
$tsEnv.Value("OSDExpectedBiosVersion") = $Expected
Write-Log "TS Expected BIOS Version set to $Expected"
} catch { Write-Log "TS environment not available." }
# Retry Counter
$RegPath = "HKLM:\SOFTWARE\Wow6432Node\GlobalClient\Applications\TS_COUNTER"
$RegName = "Dell_BIOS_Updates_Denied"
# Ensure registry path exists
if (-not (Test-Path $RegPath)) {
New-Item -Path $RegPath -Force | Out-Null
}
if (-not (Get-ItemProperty -Path $RegPath -Name $RegName -ErrorAction SilentlyContinue)) {
New-ItemProperty -Path $RegPath -Name $RegName -Value "0" -PropertyType String -Force | Out-Null
}
try {
[int]$RetryValue = Get-ItemPropertyValue -Path $RegPath -Name $RegName
}
catch {
$RetryValue = 0
}
$RetriesLeft = 5 - $RetryValue
Write-log "Retry Count: $RetryValue Retries Left: $RetriesLeft"
if ($RetryValue -ge 5) {
Write-log "Retry limit reached. FORCING BIOS upgrade."
$tsEnv.Value("BIOSUserResponse") = "FORCE"
# Warning popup (OK only)
[System.Windows.MessageBox]::Show(
"You have reached the maximum number of postpones.
A mandatory Dell BIOS upgrade will now proceed on your device.
In order to upgrade the BIOS, the computer will restart. Please ensure the power supply remains connected and any work in progress is saved before proceeding with this update. You will be able to postpone this update 4 times, at the 5th attempt, the installation cannot be postponed and will be performed.
Model: $Model
Expected BIOS Version: $Expected
Retries remaining: $RetriesLeft",
"BIOS Update Required-Mandatory",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Warning
)
Wait-ForACPower
Exit 0
}
# Show user prompt
$Message = @"
A Dell BIOS critical update needs to be performed on your device.
In order to update the BIOS, the computer will restart. Please ensure the power supply remains connected and any work in progress is saved before proceeding with this update. You will be able to postpone this update 4 times, at the 5th attempt, the installation cannot be postponed and will be performed.
Model: $Model
Expected BIOS Version: $Expected
YES → Continue with BIOS installation
NO → Postpone update
Retries remaining: $RetriesLeft
"@
$Result = [System.Windows.MessageBox]::Show($Message, "BIOS Upgrade Required",
[System.Windows.MessageBoxButton]::YesNo,
[System.Windows.MessageBoxImage]::Warning
)
switch ($Result) {
"Yes" {
Write-Log "User selected YES."
$tsEnv.Value("BIOSUserResponse") = "YES"
Wait-ForACPower
exit 0
}
"No" {
Write-Log "User selected NO. Incrementing retry count."
New-Item -Path $RegPath -Force | Out-Null
Set-ItemProperty -Path $RegPath -Name $RegName -Value "$($RetryValue + 1)"
$tsEnv.Value("BIOSUserResponse") = "NO"
Show-BIOSUpgradeNo
}
}
}
Function Wait-Userlogon{
Write-log "Waiting for user to log in..."
$timeout = 3600 # 60 minutes
$interval = 60
$elapsed = 0
while ($elapsed -lt $timeout) {
if (Get-Process explorer -ErrorAction SilentlyContinue) {
Write-log "User login detected."
return $true
}
Start-Sleep -Seconds $interval
$elapsed += $interval
}
Write-log "Timeout waiting for user login."
return $false
}
function Run-PostTSVerification {
Write-Log "===== Running $Action Action ====="
$tsEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
$WasUserLoggedBeforeReboot = ($tsEnv.Value("UserLogged") -eq "Yes")
$IsUserLoggedNow = [bool](Get-Process explorer -ErrorAction SilentlyContinue)
Write-Log "User logged before reboot: $WasUserLoggedBeforeReboot"
Write-Log "User logged now : $IsUserLoggedNow"
if ($WasUserLoggedBeforeReboot -and -not $IsUserLoggedNow) {
Write-Log "Waiting for user login because user was logged in before reboot."
$waitResult = Wait-Userlogon
if (-not $waitResult) {
Write-Log "Proceeding without user login after timeout."
}
}
else {
Write-Log "No need to wait for user login."
}
Set-ModelAndUpgradeStatus
Write-Log "===== Verifying BIOS Version After Reboot ====="
$Expected = Get-ExpectedBiosVersion
if (!$Expected) {
Write-Log "Cannot validate BIOS without expected version."
return
}
$Actual = (Get-CimInstance Win32_BIOS).SMBIOSBIOSVersion
Write-Log "Actual BIOS: $Actual Expected BIOS: $Expected"
if ($Actual.Trim().ToLower() -eq $Expected.Trim().ToLower()) {
Write-Log "BIOS upgrade SUCCESS."
$tsEnv.Value("BIOSUpgradeResult") = "SUCCESS"
$RegPath = "HKLM:\SOFTWARE\Wow6432Node\GlobalClient\Applications\TS_COUNTER"
if (Test-Path $RegPath) {
Remove-Item -Path $RegPath -Recurse -Force
Write-log "Registry key deleted successfully."
} else {
Write-log "Registry key does not exist."
}
} else {
Write-Log "BIOS upgrade FAILED."
$tsEnv.Value("BIOSUpgradeResult") = "FAILED"
}
}
function Show-BIOSUpgradeNo {
Write-Log "===== Running $Action Action ====="
[System.Windows.MessageBox]::Show(
"BIOS install Posponded successfully.",
"Upgrade Pospond",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Information
)
Exit 1234567
}
function Show-BIOSUpgradeSuccessPopup {
Write-Log "===== Running $Action Action ====="
[System.Windows.MessageBox]::Show(
"BIOS installed successfully.",
"Success",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Information
)
Write-Log "===== BIOS UPGRADE MAIN SCRIPT COMPLETED ====="
}
function Show-BIOSUpgradeFailedPopup {
Write-Log "===== Running $Action Action ====="
[System.Windows.MessageBox]::Show(
"BIOS installation failed.",
"Failed",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Error
)
Write-Log "===== BIOS UPGRADE MAIN SCRIPT COMPLETED ====="
Exit 1234567
}
switch ($Action) {
"Prompt" { Show-BIOSUpgradetPrompt }
"PostTSRun" { Run-PostTSVerification }
"SuccessPopup" { Show-BIOSUpgradeSuccessPopup }
"FailedPopup" { Show-BIOSUpgradeFailedPopup }
"CheckOnly" { Run-CheckOnly }
}
Second Script::
$ScriptFolder = Split-Path -Parent $MyInvocation.MyCommand.Definition
$BIOSFile = Get-ChildItem -Path $ScriptFolder -Filter *.exe | Select-Object -First 1
$Model = (Get-WmiObject Win32_ComputerSystem).Model
$LogoPath = join-path $ScriptFolder "Logo.png"
$LogFolder = "C:\ProgramData\LogFiles"
if (!(Test-Path $LogFolder)) { New-Item $LogFolder -ItemType Directory -Force }
$ExeLog = Join-Path $LogFolder ("BIOS_Upgrade_{0}.log" -f ($Model -replace '[\\/:*?"<>|]','_'))
function Write-Log {
param([string]$Message)
"$([datetime]::Now.ToString('yyyy-MM-dd HH:mm:ss')) - $Message" |
Out-File -FilePath $ExeLog -Append -Encoding ascii
}
Write-Log "===== Starting Dynamic BIOS Upgrade ====="
function Start-BIOSProgressUI {
Add-Type -AssemblyName PresentationFramework,WindowsBase,System.Windows.Forms
$script:UI = @{
Status = "Starting..."
Progress = 0
Window = $null
PB = $null
StatusTB = $null
PctTB = $null
OutputTB = $null
}
[xml]$XAML = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="BIOS Upgrade"
Width="820"
Height="260"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
WindowStyle="None"
Topmost="True"
Background="White"
ShowInTaskbar="True">
<Grid>
<!-- Header -->
<Border Name="Header"
Background="#0078D4"
Height="70"
VerticalAlignment="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Logo -->
<Image Name="LogoImage"
Grid.Column="0"
Width="180"
Height="48"
Margin="16,0,0,0"
Stretch="Uniform"
HorizontalAlignment="Left"
VerticalAlignment="Center"/>
<!-- Title -->
<TextBlock Grid.Column="1"
Text="BIOS Upgrade in Progress"
Foreground="White"
FontSize="22"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<!-- Minimize button -->
<Button Name="BtnMinimize"
Grid.Column="2"
Width="36"
Height="28"
Margin="0,0,12,0"
Content="—"
FontSize="16"
FontWeight="Bold"
Background="Transparent"
Foreground="White"
BorderThickness="0"
Cursor="Hand"
HorizontalAlignment="Right"
VerticalAlignment="Center"/>
</Grid>
</Border>
<!-- Content -->
<StackPanel Margin="16,80,16,16">
<TextBlock Name="StatusText"
Text="Starting..."
FontSize="16"
Margin="4,0,0,8"/>
<Grid>
<ProgressBar Name="PB"
Height="22"
Minimum="0"
Maximum="100"/>
<TextBlock Name="PctText"
Text="0%"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
<TextBox Name="OutputBox"
Margin="0,8,0,0"
Height="70"
IsReadOnly="True"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"/>
</StackPanel>
</Grid>
</Window>
"@
$Reader = New-Object System.Xml.XmlNodeReader $XAML
$Window = [Windows.Markup.XamlReader]::Load($Reader)
$script:UI.Window = $Window
$script:UI.PB = $Window.FindName("PB")
$script:UI.StatusTB = $Window.FindName("StatusText")
$script:UI.PctTB = $Window.FindName("PctText")
$script:UI.OutputTB = $Window.FindName("OutputBox")
$Logo = $Window.FindName("LogoImage")
$Header = $Window.FindName("Header")
$BtnMinimize = $Window.FindName("BtnMinimize")
$script:IsDragging = $false
$BtnMinimize.Add_Click({
$script:UI.Window.WindowState = [System.Windows.WindowState]::Minimized
})
$Header.Add_MouseLeftButtonDown({
if ($_.ClickCount -eq 2) {
if ($script:UI.Window.WindowState -eq [System.Windows.WindowState]::Minimized) {
$script:UI.Window.WindowState = [System.Windows.WindowState]::Normal
}
else {
$script:UI.Window.WindowState = [System.Windows.WindowState]::Minimized
}
}
else {
$script:UI.Window.DragMove()
}
})
if ($LogoPath -and (Test-Path $LogoPath)) {
try {
$Bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$Bitmap.BeginInit()
$Bitmap.UriSource = [Uri]$LogoPath
$Bitmap.CacheOption = [System.Windows.Media.Imaging.BitmapCacheOption]::OnLoad
$Bitmap.CreateOptions = [System.Windows.Media.Imaging.BitmapCreateOptions]::IgnoreImageCache
$Bitmap.EndInit()
$Bitmap.Freeze()
$Logo.Source = $Bitmap
$Logo.SnapsToDevicePixels = $true
$Logo.UseLayoutRounding = $true
[System.Windows.Media.RenderOptions]::SetBitmapScalingMode(
$Logo,
[System.Windows.Media.BitmapScalingMode]::HighQuality
)
}
catch {
Write-Log "Logo load failed: $_"
}
}
$Window.Show()
}
function Update-BIOSProgress {
param(
[string]$Message,
[int]$Percent
)
if (-not $script:UI.Window) { return }
if ($Message) {
$script:UI.StatusTB.Text = $Message
}
$Percent = [Math]::Max(0, [Math]::Min(100, $Percent))
$script:UI.PB.Value = $Percent
$script:UI.PctTB.Text = "$Percent%"
[System.Windows.Forms.Application]::DoEvents()
}
function Stop-BIOSProgressUI {
if ($script:UI.Window) {
$script:UI.Window.Close()
}
}
function Add-BIOSOutput {
param([string]$Text)
if ($script:UI.OutputTB) {
$script:UI.OutputTB.AppendText("$Text`r`n")
$script:UI.OutputTB.ScrollToEnd()
[System.Windows.Forms.Application]::DoEvents()
}
}
function Show-ErrorPopup {
param([string]$ExitCode)
Add-Type -AssemblyName PresentationFramework
[System.Windows.MessageBox]::Show(
"The BIOS upgrade failed.`nError Code: $ExitCode",
"BIOS Upgrade Failed",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Error
) | Out-Null
}
function Show-SuccessPopup {
Add-Type -AssemblyName PresentationFramework
$ts = New-Object -ComObject Microsoft.SMS.TSEnvironment
$RebootTime = $ts.Value("RebootTime")
[System.Windows.MessageBox]::Show(
"BIOS upgrade completed successfully. Rebooting System in $RebootTime minutes...",
"BIOS Upgrade Completed",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Information
) | Out-Null
}
try {
$ts = New-Object -ComObject Microsoft.SMS.TSEnvironment
$Password = $ts.Value("BIOSPassword")
}
catch {
Write-Log "ERROR: Cannot read TS variable BIOSPassword"
}
if (-not $BIOSFile) {
Write-Log "ERROR: No BIOS EXE found in folder: $ScriptFolder"
exit 1234567
}
$ExePath = $BIOSFile.FullName
Write-Log "Found BIOS EXE: $ExePath"
$Args = "/s /c=4 /f /forceit /l=`"$ExeLog`" /p=$Password"
Write-Log "Executing: $ExePath"
Start-BIOSProgressUI
Update-BIOSProgress "Preparing BIOS upgrade..." 1
Add-BIOSOutput "A Dell BIOS critical update needs to be performed on your device.
In order to update the BIOS, the computer will restart. Please ensure the power supply remains connected and any work in progress is saved before proceeding with this update."
$process = Start-Process -FilePath $ExePath -ArgumentList $Args -PassThru
Write-Log "Process started (PID: $($process.Id))"
$percent = 1
$tick = 0
while (-not $process.HasExited) {
Start-Sleep -Seconds 1
$tick++
if ($tick -ge 3 -and $percent -lt 95) {
$percent++
$tick = 0
Update-BIOSProgress "Flashing BIOS firmware..." $percent
}
}
$exitCode = $process.ExitCode
Update-BIOSProgress "Finalizing..." 100
Start-Sleep 1
Stop-BIOSProgressUI
if ($exitCode -in @(0, 2,3, 3010)) {
Write-Log "BIOS installation SUCCESS"
try { $ts.Value("BIOSUpgradePreReboot") = "SUCCESS" } catch {}
Write-Log "===== Completed Dynamic BIOS Upgrade ====="
Show-SuccessPopup
exit 0
}
else {
Write-Log "BIOS installation FAILED with exit code $exitCode"
try { $ts.Value("BIOSUpgradePreReboot") = "FAILED" } catch {}
Write-Log "===== Completed Dynamic BIOS Upgrade ====="
Show-ErrorPopup -ExitCode $exitCode
exit $exitCode
}
JSON Configuration:
{
"VMware20,1": "VMW201.00V.24504846.B64.2501180339",
"Latitude 5550": "1.18.1",
"Latitude 5350": "1.17.1",
"Latitude 5540": "1.24.1",
"Latitude 5340": "1.24.1",
"Latitude 5430": "1.32.1",
"Latitude 5420": "1.47.1",
"Latitude 5400": "1.41.1",
"Latitude 5410": "1.38.1",
"Latitude 5320": "1.46.0",
"Latitude 5330": "1.31.1",
"Latitude 5300": "1.37.0",
"Latitude 5310": "1.30.0",
"Latitude 5440": "1.25.1",
"Latitude 7320 DETACHABLE": "1.43.0",
"Latitude 7350 DETACHABLE": "1.15.0",
"Latitude 7210 2-in-1": "1.40.0",
"Latitude 7450": "1.16.0",
"Latitude 7390": "1.44.0",
"Latitude 7200 2-in-1": "1.38.0",
"Optiplex 5000 Micro": "1.34.1",
"Optiplex 5060 Micro": "1.32.0",
"Optiplex 5070 Micro": "1.35.0",
"Optiplex 5080 Micro": "1.33.0",
"Optiplex 5090 Micro": "1.37.0",
"Optiplex Micro plus 7010": "1.30.0",
"Optiplex Micro plus 7020": "1.20.0",
"Precision 7550": "1.41.1",
"Precision 7560": "1.42.0",
"Precision 7670": "1.32.0",
"Precision 7680": "1.24.1",
"Pro 16 Plus PB16250": "2.7.4",
"Pro 14 Plus PB14250": "2.7.4",
"Pro 13 Plus PB13250": "2.7.4",
"Pro Micro QCM1250": "1.9.2",
"Pro Micro Plus QBM1250": "1.9.2"
}
Folder Stracture::
<G>BIOS Upgrade_DC_Smart_Upgrade
| <G>BIOS_PreUpgrade
| | |<V>Set Dynamic Variables | (SMSTSDownloadProgram=Bits|BIOSPassword=********|RebootTime=10|
| | | |MachineModel=NotSet|BIOSUpgradeRequired=NotSet|OSDExpectedBiosVersion=NotSet|BIOSUserResponse=NotSet
| | | |BIOSUpgradeResult=NotSet | BIOSUpgradePreReboot=NotSet|UserLogged=NotSet|ACPower=NotSet)
| | |<C>BIOS_Upgrade_SmartConfig -Action CheckOnly | <%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -
| | | | WindowStyle | Hidden -File BIOS_Upgrade_SmartConfig.ps1 -Action CheckOnly>
| | |<C>BIOS_Upgrade_SmartConfig -Action Prompt | <ServiceUI.exe -process:explorer.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -
| | | ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File BIOS_Upgrade_SmartConfig.ps1 -Action
| | | Prompt> | (If All Conditions are true |BIOSUpgradeRequired = True|UserLogged=Yes)
| <G>BIOS_PreUpgrade_Configuration | (If any Conditions are True
| | | |If All Conditions are true
| | | | |BIOSUpgradeRequired=True
| | | | |BIOSUserResponse=Yes
| | | |If All Conditions are True
| | | | |BIOSUpgradeRequired=True
| | | | |BIOSUserResponse=Force
| | | |If All Conditions are True
| | | | |ACPower=Yes
| | | | |UserLogged=No
| | | | |BIOSUpgradeRequired=True)
| | |<B>Disable BitLocker
| | |<G>BIOS_Upgrade
| | |<V>Set OSDDoNotLogCommand to True | <OSDDoNotLogCommand=True>
| | |<C>BIOS_Upgrade - Latitude 5300 | <ServiceUI.exe -process:explorer.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -
| | | | ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -file BIOS_Upgrade.ps1> | (Select * From Win32
| | | | _ComputerSystem WHERE Model LIKE "Latitude 5300%")
| | |<V>Set OSDDoNotLogCommand to False| <OSDDoNotLogCommand=False>
| | |<G>BIOS_PostUpgrade | (If any Conditions are true
| | | | |> _SMSTSLastActionSucceeded=True
| | | | |> BIOSUpgradePreReboot=success)
| | | |<R>Restart Computer
| | | |<B>Enable BitLocker
| | | |<C>BIOS_Upgrade_SmartConfig -Action PostTSRun | <%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy
| | | |Bypass NoProfile - WindowStyle Hidden -File BIOS_Upgrade_SmartConfig.ps1 -Action
| | | |PostTSRun>
| | |<G>BIOS_UpgradeSuccess | (BIOSUpgradeResult=Success)
| | |<C>BIOS_Upgrade_SmartConfig -Action SuccessPopup | <ServiceUI.exe -process:explorer.exe %SYSTEMROOT%\System32\WindowsPowerShell
| | | \v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -
| | | File BIOS_Upgrade_SmartConfig.ps1 -Action SuccessPopup>
| <G>BIOS_UpgradeFailed | (If All Conditions are True
| | |If any Conditions are true
| | | |> _SMSTSLastActionSucceeded=False
| | | |> BIOSUpgradeResult=Failed
| | | |> BIOSUpgradePreReboot=Failed
| | |If All Conditions are True
| | | |> BIOSUserResponse=Yes)
| <B>Enable BitLocker
| <C>BIOS_Upgrade_SmartConfig -Action FailedPopup | <ServiceUI.exe -process:explorer.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe - | ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File BIOS_Upgrade_SmartConfig.ps1 - | Action FailedPopup>
No comments:
Post a Comment
Leave your valuable words here for improve better.