Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Import-Module $env:SyncroModule -DisableNameChecking
- <# Requires Chocolatey or Syncro 3rd Party Patch Policy enabled
- Reboot disable switch doesn't seem to work 100%, so schedule after hours
- Some code borrowed from https://www.cyberdrain.com/monitoring-with-powershell-monitoring-dell-driver-updates-dcu-3-1/
- 2024/5/7 - Updated with current version of Get-InstalledApps function and removal of Dell Update for Windows Universal
- 2024/7/9 - Added prerequisite check for workstation OS
- TODO:
- failure catching
- add reboot conditions
- variablize update types/severity
- # # Disable schedule and notifications
- # &$dcu /configure -scheduleManual -updatesNotification=disable
- 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
- #>
- $Reboot = $true
- $homepath = "c:\ICS" # Location to save report, DCU won't let us use Windows Temp or DCU folder
- $dcu = "${env:ProgramFiles}\Dell\CommandUpdate"
- # Prerequisite checks
- if ((Get-CimInstance -ClassName Win32_ComputerSystem).Manufacturer -notlike 'Dell*') {
- Write-Host "System Manufacturer is not Dell, exiting..."
- exit 0
- }
- if ((Get-CimInstance Win32_OperatingSystem).ProductType -ne 1) {
- Write-Host "Not a workstation OS, exiting..."
- exit 0
- }
- if (-not (Test-Path "$homepath")) { mkdir "$homepath" | Out-Null }
- if (Test-Path "$env:SystemDrive\Program Files\RepairTech\Syncro\kabuto_app_manager\choco.exe") {
- $choco = "$env:SystemDrive\Program Files\RepairTech\Syncro\kabuto_app_manager\choco.exe"
- } elseif (Test-Path "$env:AllUsersProfile\chocolatey\choco.exe") {
- $choco = "$env:AllUsersProfile\chocolatey\choco.exe"
- } elseif ($env:ChocolateyInstall) {
- $choco = $env:ChocolateyInstall
- } else {
- Write-Host "Chocolatey not found, exiting..."
- Rmm-Alert -Category "Dell Command Update" -Body "Chocolatey not found"
- exit 1
- }
- $model = (Get-CimInstance -ClassName Win32_ComputerSystem).Model
- if ($model -notlike '*OptiPlex*' -and $model -notlike '*Latitude*' -and $model -notlike '*Precision*' -and $model -notlike '*Venue*' -and $model -notlike '*XPS*') {
- Write-Host "Model not supported, installing Dell Update instead and exiting..."
- &$choco upgrade dell-update -y --no-progress
- exit 0
- }
- # Uninstall no longer updated Chocolatey package (4.6), space at the end to avoid matching dellcommandupdate-uwp
- if ((&$choco list -local) -match "dellcommandupdate ") {
- &$choco uninstall DellCommandUpdate -y --no-progress
- }
- # Uninstall any remaining Dell Update applications
- $executable = $env:windir + "\system32\msiexec.exe"
- $AppsToRemove = @(
- "Dell Command | Update"
- "Dell Command | Update for Windows 10"
- "Dell Update for Windows Universal"
- )
- function Get-InstalledApps {
- # Modified from Test-InstalledSoftware function from https://github.com/darimm/RMMFunctions
- $32BitPath = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
- $64BitPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
- # Empty array to store applications
- $Apps = @()
- # Retrieve globally installed applications
- $Apps += Get-ItemProperty "HKLM:\$32BitPath" | Where-Object { $null -ne $_.DisplayName }
- $Apps += Get-ItemProperty "HKLM:\$64BitPath" | Where-Object { $null -ne $_.DisplayName }
- # Retrieve user profile applications
- $AllProfiles = Get-CimInstance Win32_UserProfile |
- Select-Object LocalPath, SID, Loaded, Special |
- Where-Object { $_.SID -like "S-1-5-21-*" -or $_.SID -like "S-1-12-1-*" } # 5-21 regular users, 12-1 is AzureAD users
- $MountedProfiles = $AllProfiles | Where-Object { $_.Loaded -eq $true }
- $UnmountedProfiles = $AllProfiles | Where-Object { $_.Loaded -eq $false }
- $MountedProfiles | ForEach-Object {
- $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\$($_.SID)\$32BitPath" | Where-Object { $null -ne $_.DisplayName }
- $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\$($_.SID)\$64BitPath" | Where-Object { $null -ne $_.DisplayName }
- }
- $UnmountedProfiles | ForEach-Object {
- $Hive = "$($_.LocalPath)\NTUSER.DAT"
- if (Test-Path $Hive) {
- REG LOAD HKU\temp $Hive >$null
- $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\temp\$32BitPath" | Where-Object { $null -ne $_.DisplayName }
- $Apps += Get-ItemProperty -Path "Registry::\HKEY_USERS\temp\$64BitPath" | Where-Object { $null -ne $_.DisplayName }
- # Run manual GC to allow hive to be unmounted
- [GC]::Collect()
- [GC]::WaitForPendingFinalizers()
- REG UNLOAD HKU\temp >$null
- }
- }
- return $Apps
- }
- foreach ($App in $AppsToRemove) {
- Get-InstalledApps | Where-Object { $_.DisplayName -like "$App" -and $_.UninstallString -like "*MsiExec.exe*" } | ForEach-Object {
- Write-Host "Uninstalling $($_.DisplayName)..." -NoNewline
- $parameters = "/x " + $_.PSChildName + [char]32 + "/qn REBOOT=ReallySuppress /norestart"
- $errCode = (Start-Process -FilePath $executable -ArgumentList $parameters -Wait -PassThru).ExitCode
- If (($errCode -eq 0) -or ($errCode -eq 3010) -or ($errCode -eq 1605)) {
- Write-Host " Success"
- } else {
- Write-Host " Failed with error code"$errCode
- }
- }
- }
- # Install/Upgrade DCU
- if (-not (Test-Path "$dcu\DCU-CLI.exe")) {
- # Force install used incase app was uninstalled without choco package being removed
- &$choco install DellCommandUpdate-UWP -y -f --no-progress
- if (-not (Test-Path "$dcu\DCU-CLI.exe")) {
- Write-Host "DCU-CLI.exe not found, install failed, exiting..."
- Rmm-Alert -Category "Dell Command Update" -Body "DCU-CLI.exe not found, install failed"
- exit 1
- }
- } else {
- &$choco upgrade DellCommandUpdate-UWP -y --no-progress
- }
- # Turn off notifications and scheduled scans
- &"$dcu\DCU-CLI.exe" /configure -scheduleManual -updatesNotification=disable
- # See what updates are available
- &"$dcu\DCU-CLI.exe" /scan -report="$homepath"
- # Exit Code 500 means no updates found
- if ($LastExitCode -eq 500) {
- exit 0 # exit 0 so script doesn't fail
- }
- [xml]$XMLReport = Get-Content "$homepath\DCUApplicableUpdates.xml"
- # Delete report because we don't need it anymore, and sometimes fails to overwrite
- Remove-Item "$homepath\DCUApplicableUpdates.xml" -Force
- # Process report
- $AvailableUpdates = $XMLReport.updates.update
- $BIOSUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "BIOS" }).name.Count
- $ApplicationUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Application" }).name.Count
- $DriverUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Driver" }).name.Count
- $FirmwareUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Firmware" }).name.Count
- $OtherUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Other" }).name.Count
- $PatchUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Patch" }).name.Count
- $UtilityUpdates = ($AvailableUpdates | Where-Object { $_.type -eq "Utility" }).name.Count
- $RecommendedUpdates = ($AvailableUpdates | Where-Object { $_.Urgency -eq "Recommended" }).name.Count
- $UrgentUpdates = ($AvailableUpdates | Where-Object { $_.Urgency -eq "Urgent" }).name.Count
- $AvailableUpdates
- Write-Host "BIOS Updates: $BIOSUpdates"
- Write-Host "Application Updates: $ApplicationUpdates"
- Write-Host "Driver Updates: $DriverUpdates"
- Write-Host "Firmware Updates: $FirmwareUpdates"
- Write-Host "Other Updates: $OtherUpdates"
- Write-Host "Patch Updates: $PatchUpdates"
- Write-Host "Utility Updates: $UtilityUpdates"`n
- Write-Host "Recommended Updates: $RecommendedUpdates"
- Write-Host "Urgent Updates: $UrgentUpdates"
- # Apply updates
- if ($AvailableUpdates) {
- &"$dcu\DCU-CLI.exe" /ApplyUpdates -updateSeverity="Critical,Recommended" -AutoSuspendBitLocker=Enable -Reboot=Disable -ForceUpdate=Enable
- if ($LastExitCode -eq 1) { # Exit Code 1 means a reboot is required
- Write-Host "Reboot is required to finish updates."
- if ($Reboot) {
- "Reboot variable enabled, initiating reboot."
- # If Automatic Restart Sign-On is enabled, the device automatically signs in and locks
- # based on the last interactive user. After sign in, it restarts any registered applications.
- shutdown /g /f
- exit 0 # exit 0 so script doesn't fail
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement