Question

Basic Dell Command Update Worklet

  • 29 November 2023
  • 4 replies
  • 385 views

Badge

 Automox newbie here and I’m trying to create a very basic worklet that would check if a computer is a Dell and if so, run Dell Command Update. I’ve cut and pasted commands from examples posted here, but it’s not working. Below is what I’ve created. Can someone tell me what I’m doing wrong? Thank you!

 

 


4 replies

Userlevel 5
Badge +1

Hi @billb660 

 

I’ve accomplished this in the past and think this is my post from a prior time. 

 

First, pro-tip about psexec and 32-bit powershell to test your worklet on your local system to see what it does. Super helpful. Not sure if this is your issue, but file could not be found on mine because it was in a different folder. 

I’ve updated since then, so below is how I’m only focused on Applying Dell Updates if they exist. 

 

If you want super basic, then here that is. I’ve excluded silent and output log because I’ve never had them work with the apply update switch.

$x86 = 'C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe'
$x64 = 'C:\Program Files\Dell\CommandUpdate\dcu-cli.exe'
IF((Test-Path $x86) -eq $true){$dcucli = $x86}
IF((Test-Path $x64) -eq $true){$dcucli = $x64}
Start-Process -FilePath $dcucli -ArgumentList "/applyUpdates -reboot=disable" -Wait

For logging, I’ve relied on the output of "C:\ProgramData\dell\UpdateService\Log\Activity.log" which is an xml file that I’ve parsed in the code below. It is the Get-DellCommandActivity function in the code below and the output focuses on showing installed updates, which I find pretty handy when knowing what happened to all the workstations where this runs.

 

Here is my complete solution with fancy output and minimal error checking. I’m sure there is a version 3 of this code in me somewhere but I’m just passing it along as is. Enjoy:

 

Evaluation Code

$system = Get-WmiObject win32_computersystem
IF($system.Manufacturer -match "Dell"){

# find dcu-cli.exe
$x86 = 'C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe'
$x64 = 'C:\Program Files\Dell\CommandUpdate\dcu-cli.exe'
IF((Test-Path $x86) -eq $true){$dcucli = $x86}
IF((Test-Path $x64) -eq $true){$dcucli = $x64}

# scan for update
$xml = 'C:\ProgramData\dell\DCIUpdatesReport\DCUApplicableUpdates.xml'
Remove-Item $xml -force
$scan = Start-Process "$dcucli" -ArgumentList "/scan -silent -report=C:\ProgramData\dell\DCIUpdatesReport" -Wait
IF((Get-ChildItem $xml).LastWriteTime -gt (Get-Date).AddMinutes(-5)){
[xml]$updates = Get-Content "$xml"
}else{
$msg = switch ($LASTEXITCODE)
{
0 {'Command execution was successful.'}
1 {'Reboot the system to complete the operation.'}
2 {'An unknown application error has occurred'}
3 {'The current system manufacturer is not Dell.'}
4 {'The CLI was not launched with administrative privilege.'}
5 {'A reboot was pending from a previous operation.'}
6 {'Another instance of the same application (UI or CLI) is already running.'}
7 {'The application does not support the current system model.'}
8 {'No update filters have been applied or configured.'}
Default {"Unknown $LASTEXITCODE code detected."}
}
Write-Output "Dell Command Reported $msg"
}

# Get users and admins
$user = (Get-WmiObject -Class Win32_ComputerSystem).UserName
$admins = (net localgroup administrators).where({$_ -match '-{79}'},'skipuntil') -notmatch '-{79}|The command completed'

# Set threshold to install Dell Driver Updates
IF($user -in $admins){
# is an admin - instant install
$threshold = 0
}else{
# is not admin - add 7 days before install
$threshold = 7
}

IF($updates.updates.update){
# Loop and log
$log = 'C:\ProgramData\Temp\DellCommand-Automox-Worklet.txt'
Function Get-Timestamp{
return (get-date -f 'yyyy-MM-dd hh:mm tt')
}
ForEach($update in $updates.updates.update){
$age = New-TimeSpan $([datetime]$update.date) (Get-Date)
IF($age.Days -ge $threshold){
$msg = "$($update.urgency) | $($update.category) | $($update.date) | $($update.name)"
"$(Get-Timestamp)`t$msg" | out-file -FilePath $log -Append
$i++
}
}
# Missing Updates
IF($i -gt 0){
exit 1
}

}else{
# Not Missing Updates
exit 0
}

}else{
# Not Dell
exit 0
}

Remediation Code

$system = Get-WmiObject win32_computersystem
IF($system.Manufacturer -match "Dell"){

# Find versions of Dell Command installed
$scriptblock = {
$Paths = @("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall","SOFTWARE\\Wow6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
ForEach($Path in $Paths) {

Write-Verbose "Checking Path: $Path"

# Create an instance of the Registry Object and open the HKLM base key
#Try { $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer,'Registry64') } Catch { Write-Error $_ ; Continue }
Try { $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer,'Registry64') } Catch { Continue }
# Drill down into the Uninstall key using the OpenSubKey Method

Try {

$regkey=$reg.OpenSubKey($Path)

# Retrieve an array of string that contain all the subkey names
$subkeys=$regkey.GetSubKeyNames()

# Open each Subkey and use GetValue Method to return the required values for each
ForEach ($key in $subkeys){
Write-Verbose "Key: $Key"
$thisKey=$Path+"\\"+$key
Try {

$thisSubKey=$reg.OpenSubKey($thisKey)

# Prevent Objects with empty DisplayName
$DisplayName = $thisSubKey.getValue("DisplayName")

If ($DisplayName -AND $DisplayName -notmatch '^Update for|rollup|^Security Update|^Service Pack|^HotFix') {

$Date = $thisSubKey.GetValue('InstallDate')
#If ($Date) { Try { $Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null) } Catch { Write-Warning "$($Computer): $_ <$($Date)>"; $Date = $Null } }
If ($Date) { Try { $Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null) } Catch { $Date = $Null } }
# Create New Object with empty Properties
$Publisher = Try { $thisSubKey.GetValue('Publisher').Trim() } Catch { $thisSubKey.GetValue('Publisher') }
$Version = Try {
#Some weirdness with trailing [char]0 on some strings
$thisSubKey.GetValue('DisplayVersion').TrimEnd(([char[]](32,0)))
} Catch { $thisSubKey.GetValue('DisplayVersion') }
$UninstallString = Try { $thisSubKey.GetValue('UninstallString').Trim() } Catch { $thisSubKey.GetValue('UninstallString') }
$InstallLocation = Try { $thisSubKey.GetValue('InstallLocation').Trim() } Catch { $thisSubKey.GetValue('InstallLocation') }
$InstallSource = Try { $thisSubKey.GetValue('InstallSource').Trim() } Catch { $thisSubKey.GetValue('InstallSource') }
$HelpLink = Try { $thisSubKey.GetValue('HelpLink').Trim() } Catch { $thisSubKey.GetValue('HelpLink') }

$Object = [pscustomobject]@{
Computername = $env:COMPUTERNAME
DisplayName = $DisplayName
Version = $Version
InstallDate = $Date
Publisher = $Publisher
UninstallString = $UninstallString
InstallLocation = $InstallLocation
InstallSource = $InstallSource
HelpLink = $thisSubKey.GetValue('HelpLink')
EstimatedSizeMB = [decimal]([math]::Round(($thisSubKey.GetValue('EstimatedSize')*1024)/1MB,2))
}
$Object.pstypenames.insert(0,'System.Software.Inventory')
Write-Output $Object
}

} Catch { Write-Warning "$Key : $_" }
}
} Catch {}
$reg.Close()
} # end IF Paths
}
# Run the scriptblock and store results in the $64bit variable
$software = & "$env:SystemRoot\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -WindowStyle Hidden -NoProfile -NonInteractive -Command $scriptblock | where DisplayName -match 'Dell Command'

IF($software){
Write-Output "Currently $($software.Displayname) version $($software.Version) Installed. "
}

# Software is missing install
IF(-not $software){
Write-Output "Dell Command Missing. Recommend running Dell Command Install worklet. "
exit 0
}
}else{
Write-Output "Manufacturer $($system.Manufacturer) was not recognized as Dell. "
exit 0
}

# Apply Updates
Function Start-DellCommandUpdates {

# Find dcu-cli
$x86 = 'C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe'
$x64 = 'C:\Program Files\Dell\CommandUpdate\dcu-cli.exe'
IF((Test-Path $x86) -eq $true){$dcucli = $x86}
IF((Test-Path $x64) -eq $true){$dcucli = $x64}

# 2 minute timeout if dcu-cli is already running
$dcu = Get-Process dcu-cli -ErrorAction SilentlyContinue
IF($dcu){
Write-Output "dcu-cli currently running. Wait for process to complete. "
$startDate = Get-Date
do{}while((Get-Process dcu-cli -ea SilentlyContinue) -and $startDate.AddMinutes(2) -gt (Get-Date))
$dcu = Get-Process dcu-cli -ErrorAction SilentlyContinue
IF($dcu){Stop-Process dcu-cli -Force}
}
# Run dcu-cli
Write-Output "Starting Dell Command Update Process. "
Try {
Start-Process -FilePath $dcucli -ArgumentList "/applyUpdates" -Wait
$msg = switch ($LASTEXITCODE)
{
0 {'Command execution was successful.'}
1 {'Reboot the system to complete the operation.'}
2 {'An unknown application error has occurred'}
3 {'The current system manufacturer is not Dell.'}
4 {'The CLI was not launched with administrative privilege.'}
5 {'A reboot was pending from a previous operation.'}
6 {'Another instance of the same application (UI or CLI) is already running.'}
7 {'The application does not support the current system model.'}
8 {'No update filters have been applied or configured.'}
Default {"Unknown $LASTEXITCODE code detected."}
}
Write-Output "Dell Command Reported $msg"
}catch{ Start-Process -FilePath $dcucli -ArgumentList "/applyUpdates" -Wait }
}
Start-DellCommandUpdates

# Find dcu-cli
$x86 = 'C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe'
$x64 = 'C:\Program Files\Dell\CommandUpdate\dcu-cli.exe'
IF((Test-Path $x86) -eq $true){$dcucli = $x86}
IF((Test-Path $x64) -eq $true){$dcucli = $x64}

# scan for update
$xml = 'C:\ProgramData\dell\DCIUpdatesReport\DCUApplicableUpdates.xml'
Remove-Item $xml -force # always start with new scan report
$scan = Start-Process "$dcucli" -ArgumentList "/scan -silent -report=C:\ProgramData\dell\DCIUpdatesReport" -Wait
IF((Get-ChildItem $xml).LastWriteTime -gt (Get-Date).AddMinutes(-5)){
[xml]$updates = Get-Content "$xml"
}else{
$msg = switch ($LASTEXITCODE)
{
0 {'Command execution was successful.'}
1 {'Reboot the system to complete the operation.'}
2 {'An unknown application error has occurred'}
3 {'The current system manufacturer is not Dell.'}
4 {'The CLI was not launched with administrative privilege.'}
5 {'A reboot was pending from a previous operation.'}
6 {'Another instance of the same application (UI or CLI) is already running.'}
7 {'The application does not support the current system model.'}
8 {'No update filters have been applied or configured.'}
Default {"Unknown $LASTEXITCODE code detected."}
}
Write-Output "Dell Command Reported $msg"
IF($LASTEXITCODE -eq 5){Write-Output "Reboot before running again. "; exit 0}
IF((Test-Path $xml) -eq $false){Write-Output "Failed to Scan."}
}

# Get Activity
Function Get-DellCommandActivity {
# Get Activity Log and parse intalled updates in last 24 hours
[xml]$a = Get-Content "C:\ProgramData\dell\UpdateService\Log\Activity.log"
$range = (Get-Date).AddHours(-24)
# Write output on Checking Updates
$events = $a.LogEntries.LogEntry | Select timestamp,message | where {[datetime]$_.timestamp -gt $range -and ($_.message -match 'found' -or $_.message -match 'Checking for updates' -or $_.message -match 'verified')} | % {
$timestamp = (Get-Date $_.timestamp -Format 'yyyy-MM-dd hh:mm tt')
$message = $_.message.replace(' verified.','')
[pscustomobject] @{
timestamp = $timestamp
message = $message
}
}
foreach ($event in $events)
{
Write-Output "$($event.timestamp) $($event.message). "
}
}
#Write-Output "Attempting to Install Dell Command Updates."
$activity = Get-DellCommandActivity

# Write Activity to Log
foreach ($event in $activity){
Write-Output "$event"
}

# If no activity existed
IF($activity.count -eq 0){
# Find dcu-cli
$x86 = 'C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe'
$x64 = 'C:\Program Files\Dell\CommandUpdate\dcu-cli.exe'
IF((Test-Path $x86) -eq $true){$dcucli = $x86}
IF((Test-Path $x64) -eq $true){$dcucli = $x64}

# if Dell Command is running stop the process
Write-Output "Something went wrong. Trying to run Dell Command Update again. "
Get-Process dcu-cli -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue -Force

Start-DellCommandUpdates

# Get Activity
$activity = Get-DellCommandActivity
foreach ($event in $activity){
Write-Output "$event"
}

# If activity still does not exist
IF($activity.count -eq 0){
IF(Test-Path $dcucli){
Write-Output "Something isn't working right. Recommend running this locally and analyzing output: '$dcucli' /applyUpdates "
Write-Output $activity
}else{Write-Output "Unable to locate Dell Command. "}
}
}

 

Badge

Thanks Jack. Will give it a try.

Badge

Hi Jack.

I ran your Worklet on a Dell laptop that I know has 5 updates available updates (manually ran Dell Command Update but did not install updates) and here’s what the activity log shows...

It appears to be checking for updates but not installing them. Also, the activity log on the laptop does not show any updates installed.

Any suggestions?

Badge

Please disregard my previous message. Your worklet is working like a champ. I just needed to be more patient. Thanks again.

Reply