I have wanted to get the process of flashing the BIOS into the WinPE environment for quite a while. With the help of Sapien's PowerShell Studio, I finally wrote the script to make this possible. The purpose is that it can flash it much quicker in the WinPE environment and it also gives two opportunities for he BIOS to be flashed during the build process. On some Dell machines, if the BIOS version is too far behind, there is an intermediary BIOS update that must be applied before the latest update can be. This gives the build the opportunity to get past that intermediary and apply the latest update before the build is completed.
To use this script, you will need to first install the Dell Command | Update on a system. If you are using the x86 version of WinPE, then install it on an x86 PC. The same on an x64 machine. Copy all of the contents of the %PROGRAMFILES%\Dell\CommandUpdate folder to a folder on a network share. Next, copy the msi.dll file from the %WINDIR%\System32 folder to the same folder share.
I created a task sequence folder and then put three task sequences underneath it.
Now it's time to create the Run Command Line task sequence. The first is to map to the folder share where you copied the CommandUpdate folder to. I used T: as my drive letter and used the following command: net use t: \\<NetworkShareFolder> /USER:<domain>\<username> <Password>. This is not recorded in any of the logs, so you don't risk the password being seen by unwanted eyes so long as they cannot access the task sequence.
The second task sequence is to install and update the Dell BIOS. This is also a Run Command Line sequence. The command line I use is: powershell.exe -executionpolicy bypass -file t:\install.ps1.
The final task sequence is unmapping the network drive via a Run Command Line sequence. The command line for this is net use t: /delete
I have also included in the script the ability to apply an XML file to the dcu-cli.exe. The XML file specifies what driver types to apply to the system. It looks for the XML file in the same directory as the PowerShell script. I found that if I execute the dcu-cli.exe with no switches, it does try to install one driver update to the WinPE environment, but it fails and continues to install the BIOS update with no issues.
Here is a video of the tool in action during the initial phase of the build process:
You can download the script from here.
To use this script, you will need to first install the Dell Command | Update on a system. If you are using the x86 version of WinPE, then install it on an x86 PC. The same on an x64 machine. Copy all of the contents of the %PROGRAMFILES%\Dell\CommandUpdate folder to a folder on a network share. Next, copy the msi.dll file from the %WINDIR%\System32 folder to the same folder share.
I created a task sequence folder and then put three task sequences underneath it.
Now it's time to create the Run Command Line task sequence. The first is to map to the folder share where you copied the CommandUpdate folder to. I used T: as my drive letter and used the following command: net use t: \\<NetworkShareFolder> /USER:<domain>\<username> <Password>. This is not recorded in any of the logs, so you don't risk the password being seen by unwanted eyes so long as they cannot access the task sequence.
The second task sequence is to install and update the Dell BIOS. This is also a Run Command Line sequence. The command line I use is: powershell.exe -executionpolicy bypass -file t:\install.ps1.
The final task sequence is unmapping the network drive via a Run Command Line sequence. The command line for this is net use t: /delete
I have also included in the script the ability to apply an XML file to the dcu-cli.exe. The XML file specifies what driver types to apply to the system. It looks for the XML file in the same directory as the PowerShell script. I found that if I execute the dcu-cli.exe with no switches, it does try to install one driver update to the WinPE environment, but it fails and continues to install the BIOS update with no issues.
Here is a video of the tool in action during the initial phase of the build process:
You can download the script from here.
UpdateBIOSWinPE.ps1
1: <#
2: .SYNOPSIS
3: Install Dell Command | Update and Update the BIOS
4:
5: .DESCRIPTION
6: Copy over the Dell Command | Update and install the BIOS
7:
8: .PARAMETER Source
9: Source folder containing the Dell Command | Update files
10:
11: .PARAMETER Destination
12: Location to copy the Dell Command | Update files to
13:
14: .PARAMETER XMLFile
15: XML file that limits the Dell Command | Update to only scan for a BIOS update
16:
17: .NOTES
18: ===========================================================================
19: Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.120
20: Created on: 4/27/2016 10:17 AM
21: Created by: Mick Pletcher
22: Organization:
23: Filename: UpdateBIOSWinPE.ps1
24: ===========================================================================
25: #>
26: [CmdletBinding()]
27: param
28: (
29: [string]$Source = 't:\',
30: [string]$Destination = 'x:\DCU',
31: [string]$XMLFile
32: )
33:
34: function Copy-Folder {
35: <#
36: .SYNOPSIS
37: Copy Folder
38:
39: .DESCRIPTION
40: Copy folder to destination
41:
42: .PARAMETER SourceFolder
43: Folder to copy contents from
44:
45: .PARAMETER DestinationFolder
46: Folder to copy contents to
47:
48: .PARAMETER Subfolders
49: Include all subfolders
50:
51: .PARAMETER Mirror
52: Mirror the destination folder with the source folder. Contents that exist in the destination folder, but not in the source folder, will be deleted.
53:
54: .EXAMPLE
55: PS C:\> Copy-Folder -SourceFolder 'Value1' -DestinationFolder 'Value2'
56:
57: .NOTES
58: Additional information about the function.
59: #>
60:
61: [CmdletBinding()]
62: param
63: (
64: [string]$SourceFolder,
65: [string]$DestinationFolder,
66: [ValidateSet($true, $false)][boolean]$Subfolders = $false,
67: [ValidateSet($true, $false)][boolean]$Mirror = $false
68: )
69:
70: $Executable = $env:windir + "\system32\Robocopy.exe"
71: $Switches = $SourceFolder + [char]32 + $DestinationFolder + [char]32 + "/eta"
72: If ($Subfolders -eq $true) {
73: $Switches = $Switches + [char]32 + "/e"
74: }
75: If ($Mirror -eq $true) {
76: $Switches = $Switches + [char]32 + "/mir"
77: }
78: Write-Host "Copying "$SourceFolder"....." -NoNewline
79: $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode
80: If (($ErrCode -eq 0) -or ($ErrCode -eq 1)) {
81: Write-Host "Success" -ForegroundColor Yellow
82: } else {
83: Write-Host "Failed with error code"$ErrCode -ForegroundColor Red
84: }
85: }
86:
87: function Update-BIOS {
88: <#
89: .SYNOPSIS
90: Update to the latest BIOS Version
91:
92: .DESCRIPTION
93: Execute the DCU-CLI.exe to query Dell for the latest BIOS version
94:
95: .NOTES
96: Additional information about the function.
97: #>
98:
99: [CmdletBinding()]
100: param ()
101:
102: $Executable = $Destination + "\dcu-cli.exe"
103: If ($XMLFile -eq "") {
104: $Switches = " "
105: } else {
106: $XMLFile = $Destination + "\" + $XMLFile
107: $Switches = "/policy" + [char]32 + $XMLFile
108: }
109: #$Switches = " "
110: Write-Host "Updating BIOS....." -NoNewline
111: $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode
112: If ($ErrCode -eq 0) {
113: Write-Host "Success" -ForegroundColor Yellow
114: } else {
115: Write-Host "Failed with error code"$ErrCode -ForegroundColor Red
116: }
117: }
118:
119: #Copy contents of the Dell Command | Update folder to the WinPE directory
120: Copy-Folder -SourceFolder $Source -DestinationFolder $Destination -Subfolders $true -Mirror $true
121: #Copy msi.dll to the WinPE system32 folder to make msiexec.exe functional
122: Copy-Item -Path $Destination"\msi.dll" -Destination "x:\windows\system32" -Force
123: #Execute the dcu-cli.exe to update the BIOS
124: Update-BIOS
125:
Hello Mick,
ReplyDeleteI ran the script on my Latitude E5430, but I received the following error:
Failed with error code 2
Please advise.
Thank you!
That is a fatal error from the DCU-CLI.exe. Do you have the correct msi.dll copied over? It must come from the same architecture as the WinPE is. I am using 32-bit WinPE 5.0, therefor I pulled the msi.dll from a windows 8.1 32-bit machine.
DeleteHi Mick,
ReplyDeleteI tried doing this in WinPE 10 using DCU 2.1.1 and I always seem to receive an error 3 when doing this on an OptiPlex 3020 with A02 BIOS installed. I ran a log and it is tracing to Dell's FTP site OK, despite the fact that I'm booting into WinPE 10 using a USB key as PoC before I bring down my production boot.wim and use DISM to inject the PowerShell modules into it. I'm not certain why that would make a difference, but maybe it does.
I am not sure what I might be doing wrong. It fails every time. I want to be able to use a specific BIOS update and only have the one install. I believe i need to use the config xml, but not sure what to do exactly.
ReplyDeleteI never could get the .XML file to work correctly. The best I could do was to just execute the dcu-cli.exe with no parameters.
DeleteThank you for this blog post and the script! The issue I face is after dcu-cli.exe runs I get the message "The image file X:\DCU\InvColPC.exe is valid, but is for a machine type other than the current machine." I replaced the files I got from my laptop (an E7470) with those from another exact model machine (Optiplex 3070 Micro) wondering if there was some difference, but it didn't fix it. I know that would typically refer to an x86 vs x64 install or something similar, but don't see how to fix this.
ReplyDeleteAny ideas?
Thanks