15 April 2016

Using PowerShell to control Dell Command | Update for drivers and BIOS updates

The Dell Command | Update is a great tool to use, but it also lacks some features that I have implemented in the following script. During system builds, I have the application to update all drivers and the BIOS. The features I have included are:
  1. Ability to disable the BIOS password
  2. Ability to either run the dcu-cli.exe on either a 32-bit or 64-bit machine
  3. Ability to apply XML policies
For features 1 and 3, if the parameters are not populated, they are skipped over. If option 3 is left blank, it runs the dcu-cli.exe to update all Dell applications, BIOS, and drivers. I know that if you are going to flash the BIOS, the BIOS password is then cleared, but I figured I would add this feature just if you wanted to make sure it was done.

Here is an example of how it is integrated in MDT:


As far as where it is in the task sequences, I placed it within the State Restore and after the first Windows Update sequence.

You can download the script from here.

Update.ps1
1:  <#  
2:       .SYNOPSIS  
3:            Update Dell drivers, Dell Applications, and Dell BIOS via Dell Command | Update  
4:         
5:       .DESCRIPTION  
6:            Uses Dell Command | Update to update all drivers, BIOS, and Dell applications. Everything can be entered through the parameters without the need to modify the code.  
7:         
8:       .PARAMETER BIOSPassword  
9:            If no BIOS Password is submitted, then the script will skip over clearing disabling the BIOS Password.  
10:         
11:       .PARAMETER Policy  
12:            Name of the custom policy file that configures what updates to install.  
13:         
14:       .PARAMETER ConsoleTitle  
15:            Title of the PowerShell Window  
16:    
17:       .EXAMPLE  
18:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update" -Policy "BIOS.xml" -BIOSPassword "Pwd"  
19:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update" -Policy "BIOS.xml"  
20:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update" -BIOSPassword "Pwd"  
21:            powershell.exe -file Update.ps1 -ConsoleTitle "Dell Command | Update"  
22:         
23:       .NOTES  
24:            ===========================================================================  
25:            Created with:      SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.99  
26:            Created on:       1/29/2016 2:59 PM  
27:            Created by:       Mick Pletcher  
28:            Organization:  
29:            Filename:        Update.ps1  
30:            ===========================================================================  
31:  #>  
32:  [CmdletBinding()]  
33:  param  
34:  (  
35:            [string]$BIOSPassword,  
36:            [string]$Policy,  
37:            [string]$ConsoleTitle = " "  
38:  )  
39:    
40:  function Get-RelativePath {  
41:  <#  
42:       .SYNOPSIS  
43:            Get the relative path  
44:         
45:       .DESCRIPTION  
46:            Returns the location of the currently running PowerShell script  
47:         
48:       .NOTES  
49:            Additional information about the function.  
50:  #>  
51:         
52:       [CmdletBinding()][OutputType([string])]  
53:       param ()  
54:         
55:       $Path = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
56:       Return $Path  
57:  }  
58:    
59:  function Set-ConsoleTitle {  
60:  <#  
61:       .SYNOPSIS  
62:            Console Title  
63:         
64:       .DESCRIPTION  
65:            Sets the title of the PowerShell Console  
66:         
67:       .PARAMETER Title  
68:            Title of the PowerShell console  
69:         
70:       .NOTES  
71:            Additional information about the function.  
72:  #>  
73:         
74:       [CmdletBinding()]  
75:       param  
76:       (  
77:            [Parameter(Mandatory = $true)][String]  
78:            $Title  
79:       )  
80:         
81:       $host.ui.RawUI.WindowTitle = $Title  
82:  }  
83:    
84:  function Get-Architecture {  
85:  <#  
86:       .SYNOPSIS  
87:            System Architecture  
88:         
89:       .DESCRIPTION  
90:            Determine if the system is x86 or x64. It will then return "32-bit" or "64-bit"  
91:         
92:       .NOTES  
93:            Additional information about the function.  
94:  #>  
95:         
96:       [CmdletBinding()]  
97:       param ()  
98:         
99:       $Architecture = Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture  
100:       $Architecture = $Architecture.OSArchitecture  
101:       #Returns 32-bit or 64-bit  
102:       Return $Architecture  
103:  }  
104:    
105:  function Install-Updates {  
106:  <#  
107:       .SYNOPSIS  
108:            Install Dell Updates  
109:         
110:       .DESCRIPTION  
111:            This will install the Dell drivers, applications, and BIOS updates.  
112:         
113:       .PARAMETER DisplayName  
114:            Title to display in the PowerShell Output Console  
115:         
116:       .PARAMETER Executable  
117:            32-bit or 64-bit dcu-cli executable to execute  
118:         
119:       .PARAMETER Switches  
120:            Switches when executing the DCU-CLI executable  
121:         
122:       .NOTES  
123:            Additional information about the function.  
124:  #>  
125:         
126:       [CmdletBinding()]  
127:       param  
128:       (  
129:            [String]  
130:            $DisplayName,  
131:            [String]  
132:            $Executable,  
133:            [String]  
134:            $Switches  
135:       )  
136:         
137:       Write-Host "Install"$DisplayName"....." -NoNewline  
138:       If ((Test-Path $Executable) -eq $true) {  
139:            $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Switches -Wait -Passthru).ExitCode  
140:       } else {  
141:            $ErrCode = 1  
142:       }  
143:       If (($ErrCode -eq 0) -or ($ErrCode -eq 1) -or ($ErrCode -eq 3010)) {  
144:            Write-Host "Success" -ForegroundColor Yellow  
145:       } else {  
146:            Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
147:       }  
148:         
149:  }  
150:    
151:  function Set-BIOSSetting {  
152:  <#  
153:       .SYNOPSIS  
154:            Configure BIOS Settings  
155:         
156:       .DESCRIPTION  
157:            Uses the CCTK.exe to configure Dell BIOS settings  
158:         
159:       .PARAMETER Name  
160:            Display name of the BIOS setting  
161:         
162:       .PARAMETER Option  
163:            Technical name of the BIOS setting  
164:         
165:       .PARAMETER Setting  
166:            Switches for the Option parameter  
167:         
168:       .PARAMETER Drives  
169:            Populated if the Set-BIOSSetting is being used to configure the drive boot sequences  
170:         
171:       .PARAMETER Architecture  
172:            Designates if the OS is x86 or x64  
173:         
174:       .NOTES  
175:            Additional information about the function.  
176:  #>  
177:         
178:       [CmdletBinding()]  
179:       param  
180:       (  
181:            [string]  
182:            $Name,  
183:            [string]  
184:            $Option,  
185:            [string]  
186:            $Setting,  
187:            [string]  
188:            $Drives,  
189:            [string]  
190:            $Architecture  
191:       )  
192:         
193:       If ($Architecture -eq "32-bit") {  
194:            $EXE = $Env:PROGRAMFILES + "\Dell\Command Configure\X86\cctk.exe"  
195:       } else {  
196:            $EXE = ${env:ProgramFiles(x86)} + "\Dell\Command Configure\X86_64\cctk.exe"  
197:       }  
198:       $Argument = "--" + $Option + "=" + $Setting  
199:       Write-Host $Name"....." -NoNewline  
200:       If ((Test-Path $EXE) -eq $true) {  
201:            $ErrCode = (Start-Process -FilePath $EXE -ArgumentList $Argument -Wait -Passthru).ExitCode  
202:       } else {  
203:            $ErrCode = 1  
204:       }  
205:       If (($ErrCode -eq 0) -or ($ErrCode -eq 240) -or ($ErrCode -eq 241)) {  
206:            Write-Host "Success" -ForegroundColor Yellow  
207:       } elseIf ($ErrCode -eq 119) {  
208:            Write-Host "Unavailable" -ForegroundColor Green  
209:       } else {  
210:            Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
211:       }  
212:  }  
213:    
214:  cls  
215:  Set-ConsoleTitle -Title $ConsoleTitle  
216:  $Architecture = Get-Architecture  
217:  If ($BIOSPassword -ne "") {  
218:       Set-BIOSSetting -Name "Disable BIOS Password" -Option "valsetuppwd" -Setting $BIOSPassword" --setuppwd=" -Drives "" -Architecture $Architecture  
219:  }  
220:  If ($Architecture -eq "32-bit") {  
221:       $EXE = $Env:PROGRAMFILES + "\Dell\CommandUpdate\dcu-cli.exe"  
222:  } else {  
223:       $EXE = ${env:ProgramFiles(x86)} + "\Dell\CommandUpdate\dcu-cli.exe"  
224:  }  
225:  If ($Policy -eq "") {  
226:       $Parameters = " "  
227:  } else {  
228:       $RelativePath = Get-RelativePath  
229:       $Parameters = "/policy " + [char]34 + $RelativePath + $Policy + [char]34  
230:  }  
231:  If ((Test-Path $EXE) -eq $true) {  
232:       Install-Updates -DisplayName "Update Dell Components" -Executable $EXE -Switches $Parameters  
233:  } else {  
234:       Exit 1  
235:  }  

14 comments:

  1. Great script, can you lend a hand getting it installed? It looks as it if is assuming that the Dell Command Utility is already installed which I have been able to accomplish. But it also looks as if you are able to handle the checking to make sure this is only being run on Dell systems.

    ReplyDelete
    Replies
    1. Are you using MDT or SCCM to image the machines?

      Delete
  2. I ran the Dell Command Utility on my OptiPlex 7040 and it installed all drivers except for 2. Have you ever had drivers that the utility would not install that you had to go get manually?

    ReplyDelete
    Replies
    1. Yes. I have seen that happen before. Do you get your drivers from this site? http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment

      Delete
    2. I use MDT to do my images not SCCM. Mick, yes I use that enterprise site to get my drivers so I included the previously missing drivers to the boot image so that is resolved now. I also am re-doing my "golden" images to include Dell Command Update already installed so all i have to do is setup a task sequence for this script above to run but I am not 100% clear on how it is used. I haven't found the screenshot you posted yet.

      Delete
  3. Would like to also see where you integrate this in the task sequence. Are you using this with or instead of driver packages?

    ReplyDelete
    Replies
    1. I just added two screenshot to this blog showing how it is used.

      Delete
    2. I see the screenshots above... interesting that it is setup as an install application that you are selecting in your task sequence. Is there any reason why you didn't just add a "Run PowerShell Script" action pointing to your %SCRIPTROOT%\Update.ps1? I am doing a WMI Query to only run on Dell Systems which is working fine. I see in your screenshot that you are disabling the BIOS password on your systems. If we don't use one at all, is it ok to just run the script without any params and it just updates as normal?

      Delete
    3. I think what Garrett means and what I am curious to know is how you are using this in your task sequence. What section is it being run in, are there any situations where you run the update again? I am dealing with a brand new model of Dell, the Latitude E5570 and it ran your script during the deployment process, installed a couple of drivers and left about 13 drivers to still install. I am wondering how you would overcome this and still maintain the small driver database for MDT.

      Delete
    4. It is in the State Restore and after the first Windows Update sequence. Were the 13 drivers that were left detected when you reran the dcu-cli?

      Delete
  4. Mick, when running this in TS with SCCM I keep getting " CLI: Error: Check for updates ended. (System Scan failed)" from the activity.xml (the log for DCU-CLI). Did you run into this as well? If so, how did you work around it?

    ReplyDelete
    Replies
    1. I don't. Is the machine under a GPO that could possibly be affecting it? Does the machine have internet access during a build?

      Delete
  5. Hi Mick. Thanks for providing the script. How do you deal with driver updates rebooting the task sequence? It appears some driver updates will reboot after installation even though you aren't using the /reboot cmd line switch. When this happens the task sequence stops. If you restart it manually you get the message about another deployment in process.

    ReplyDelete
    Replies
    1. Good question. I have not encountered that yet. add /hidden to the parameters variable in the script and see if that stops the reboot.

      Delete