Advertisement
nullzilla

Task - Dell Command Update

May 11th, 2021 (edited)
3,473
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Import-Module $env:SyncroModule -DisableNameChecking
  2.  
  3. <# Requires Chocolatey or Syncro 3rd Party Patch Policy enabled
  4. Reboot disable switch doesn't seem to work 100%, so schedule after hours
  5. Some code borrowed from https://www.cyberdrain.com/monitoring-with-powershell-monitoring-dell-driver-updates-dcu-3-1/
  6.  
  7. 2024/5/7 - Updated with current version of Get-InstalledApps function and removal of Dell Update for Windows Universal
  8.  
  9. TODO:
  10. failure catching
  11. add reboot conditions
  12. CLI Reference: https://www.dell.com/support/manuals/en-us/command-update/dellcommandupdate_rg/dell-command-|-update-cli-commands?guid=guid-92619086-5f7c-4a05-bce2-0d560c15e8ed&lang=en-us
  13. #>
  14.  
  15. $Reboot = $true
  16. $homepath = "c:\ICS" # Location to save report, DCU won't let us use Windows Temp or DCU folder
  17. $dcu = "${env:ProgramFiles}\Dell\CommandUpdate"
  18.  
  19. # Prerequisite checks
  20. if (-not (Test-Path "$homepath")) { mkdir "$homepath" | Out-Null }
  21. if ((Get-CimInstance -ClassName Win32_ComputerSystem).Manufacturer -notlike 'Dell*') {
  22.     Write-Host "System Manufacturer is not Dell, exiting..."
  23.     exit 0
  24. }
  25. if (Test-Path "$env:SystemDrive\Program Files\RepairTech\Syncro\kabuto_app_manager\choco.exe") {
  26.     $choco = "$env:SystemDrive\Program Files\RepairTech\Syncro\kabuto_app_manager\choco.exe"
  27. } elseif (Test-Path "$env:AllUsersProfile\chocolatey\choco.exe") {
  28.     $choco = "$env:AllUsersProfile\chocolatey\choco.exe"
  29. } elseif ($env:ChocolateyInstall) {
  30.     $choco = $env:ChocolateyInstall
  31. } else {
  32.     Write-Host "Chocolatey not found, exiting..."
  33.     Rmm-Alert -Category "Dell Command Update" -Body "Chocolatey not found"
  34.     exit 1
  35. }
  36. $model = (Get-CimInstance -ClassName Win32_ComputerSystem).Model
  37. if ($model -notlike '*OptiPlex*' -and $model -notlike '*Latitude*' -and $model -notlike '*Precision*' -and $model -notlike '*Venue*' -and $model -notlike '*XPS*') {
  38.     Write-Host "Model not supported, installing Dell Update instead and exiting..."
  39.     &$choco upgrade dell-update -y --no-progress
  40.     exit 0
  41. }
  42.  
  43. # Uninstall no longer updated Chocolatey package (4.6), space at the end to avoid matching dellcommandupdate-uwp
  44. if ((&$choco list -local) -match "dellcommandupdate ") {
  45.     &$choco uninstall DellCommandUpdate -y --no-progress
  46. }
  47.  
  48. # Uninstall any remaining Dell Update applications
  49. $executable = $env:windir + "\system32\msiexec.exe"
  50. $AppsToRemove = @(
  51.     "Dell Command | Update"
  52.     "Dell Command | Update for Windows 10"
  53.     "Dell Update for Windows Universal"
  54. )
  55. function Get-InstalledApps {
  56.     # Modified from Test-InstalledSoftware function from https://github.com/darimm/RMMFunctions
  57.     $32BitPath = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
  58.     $64BitPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
  59.     # Empty array to store applications
  60.     $Apps = @()
  61.     # Retrieve globally installed applications
  62.     $Apps += Get-ItemProperty "HKLM:\$32BitPath" | Where-Object { $null -ne $_.DisplayName }
  63.     $Apps += Get-ItemProperty "HKLM:\$64BitPath" | Where-Object { $null -ne $_.DisplayName }
  64.     # Retrieve user profile applications
  65.     $AllProfiles = Get-CimInstance Win32_UserProfile |
  66.         Select-Object LocalPath, SID, Loaded, Special |
  67.             Where-Object { $_.SID -like "S-1-5-21-*" -or $_.SID -like "S-1-12-1-*" } # 5-21 regular users, 12-1 is AzureAD users
  68.     $MountedProfiles = $AllProfiles | Where-Object { $_.Loaded -eq $true }
  69.     $UnmountedProfiles = $AllProfiles | Where-Object { $_.Loaded -eq $false }
  70.     $MountedProfiles | ForEach-Object {
  71.         $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\$($_.SID)\$32BitPath" | Where-Object { $null -ne $_.DisplayName }
  72.         $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\$($_.SID)\$64BitPath" | Where-Object { $null -ne $_.DisplayName }
  73.     }
  74.     $UnmountedProfiles | ForEach-Object {
  75.         $Hive = "$($_.LocalPath)\NTUSER.DAT"
  76.         if (Test-Path $Hive) {
  77.             REG LOAD HKU\temp $Hive >$null
  78.             $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\temp\$32BitPath" | Where-Object { $null -ne $_.DisplayName }
  79.             $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\temp\$64BitPath" | Where-Object { $null -ne $_.DisplayName }
  80.             # Run manual GC to allow hive to be unmounted
  81.             [GC]::Collect()
  82.             [GC]::WaitForPendingFinalizers()
  83.             REG UNLOAD HKU\temp >$null
  84.         }
  85.     }
  86.     return $Apps
  87. }
  88. foreach ($App in $AppsToRemove) {
  89.     Get-InstalledApps | Where-Object { $_.DisplayName -like "*$App*" -and $_.UninstallString -like "*MsiExec.exe*" } | ForEach-Object {
  90.         Write-Host "Uninstalling $($_.DisplayName)..." -NoNewline
  91.         $parameters = "/x " + $_.PSChildName + [char]32 + "/qn REBOOT=ReallySuppress /norestart"
  92.         $errCode = (Start-Process -FilePath $executable -ArgumentList $parameters -Wait -PassThru).ExitCode
  93.         If (($errCode -eq 0) -or ($errCode -eq 3010) -or ($errCode -eq 1605)) {
  94.             Write-Host "  Success"
  95.         } else {
  96.             Write-Host "  Failed with error code"$errCode
  97.         }
  98.     }
  99. }
  100.  
  101. # Install/Upgrade DCU
  102. if (-not (Test-Path "$dcu\DCU-CLI.exe")) {
  103.     # Force install used incase app was uninstalled without choco package being removed
  104.     &$choco install DellCommandUpdate-UWP -y -f --no-progress
  105.     if (-not (Test-Path "$dcu\DCU-CLI.exe")) {
  106.         Write-Host "DCU-CLI.exe not found, install failed, exiting..."
  107.         Rmm-Alert -Category "Dell Command Update" -Body "DCU-CLI.exe not found, install failed"
  108.         exit 1
  109.     }
  110. } else {
  111.     &$choco upgrade DellCommandUpdate-UWP -y --no-progress
  112. }
  113.  
  114. # See what updates are available
  115. &"$dcu\DCU-CLI.exe" /scan -report="$homepath"
  116.  
  117. # Exit Code 500 means no updates found
  118. if ($LastExitCode -eq 500) {
  119.     exit 0 # exit 0 so script doesn't fail
  120. }
  121.  
  122. [xml]$XMLReport = Get-Content "$homepath\DCUApplicableUpdates.xml"
  123. # Delete report because we don't need it anymore, and sometimes fails to overwrite
  124. Remove-Item "$homepath\DCUApplicableUpdates.xml" -Force
  125.  
  126. # Process report
  127. $AvailableUpdates = $XMLReport.updates.update
  128. $BIOSUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "BIOS" }).name.Count
  129. $ApplicationUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Application" }).name.Count
  130. $DriverUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Driver" }).name.Count
  131. $FirmwareUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Firmware" }).name.Count
  132. $OtherUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Other" }).name.Count
  133. $PatchUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Patch" }).name.Count
  134. $UtilityUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Utility" }).name.Count
  135. $RecommendedUpdates = ($AvailableUpdates | Where-Object { $_.Urgency -eq "Recommended" }).name.Count
  136. $UrgentUpdates = ($AvailableUpdates | Where-Object { $_.Urgency -eq "Urgent" }).name.Count
  137. $AvailableUpdates
  138. Write-Host "BIOS Updates: $BIOSUpdates"
  139. Write-Host "Application Updates: $ApplicationUpdates"
  140. Write-Host "Driver Updates: $DriverUpdates"
  141. Write-Host "Firmware Updates: $FirmwareUpdates"
  142. Write-Host "Other Updates: $OtherUpdates"
  143. Write-Host "Patch Updates: $PatchUpdates"
  144. Write-Host "Utility Updates: $UtilityUpdates"`n
  145. Write-Host "Recommended Updates: $RecommendedUpdates"
  146. Write-Host "Urgent Updates: $UrgentUpdates"
  147.  
  148. # Apply updates
  149. if ($AvailableUpdates) {
  150.     &"$dcu\DCU-CLI.exe" /ApplyUpdates -updateSeverity="Critical,Recommended" -AutoSuspendBitLocker=Enable -Reboot=Disable -ForceUpdate=Enable
  151.     if ($LastExitCode -eq 1) { # Exit Code 1 means a reboot is required
  152.         Write-Host "Reboot is required to finish updates."
  153.         if ($Reboot) {
  154.             "Reboot variable enabled, initiating reboot."
  155.             # If Automatic Restart Sign-On is enabled, the device automatically signs in and locks
  156.             # based on the last interactive user. After sign in, it restarts any registered applications.
  157.             shutdown /g /f
  158.             exit 0 # exit 0 so script doesn't fail
  159.         }
  160.     }
  161. }
  162.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement