Public/Dell.DCU/Public/Get-DCUAppUpdates.ps1
|
Function Get-DCUAppUpdates { [CmdletBinding()] param ( [Parameter(Mandatory=$False)] [ValidateLength(4,4)] [string]$SystemSKUNumber, [switch]$Latest, [switch]$Install, [switch]$AutoInstallPreReqs, [switch]$UseWebRequest, [switch]$CheckPreReqs, [string]$DownloadPath = "$env:ProgramData\OEMWrapPS\DellCabDownloads" ) $DownloadPathSpecified = $PSBoundParameters.ContainsKey('DownloadPath') $Manufacturer = (Get-CimInstance -ClassName Win32_ComputerSystem).Manufacturer if (!($SystemSKUNumber)) { if ($Manufacturer -notmatch "Dell"){return "This Function is only for Dell Systems"} $SystemSKUNumber = (Get-CimInstance -ClassName Win32_ComputerSystem).SystemSKUNumber } $temproot = "$env:ProgramData\OEMWrapPS" $DellCabExtractPath = "$temproot\DellCabDownloads\DellCabExtract" $Apps = Get-DCUUpdateList -SystemSKUNumber $SystemSKUNumber -updateType application | Select-Object -Property PackageID, Name, ReleaseDate, DellVersion, VendorVersion, Path $CommandUpdateApps = $Apps | Where-Object {$_.Name -like "*Command | Update*"} | Sort-Object -Property VendorVersion $CommandUpdateAppsLatest = $CommandUpdateApps | Select-Object -Last 1 if ($CommandUpdateAppsLatest){ if ($Install){ [Version]$DCUVersion = $CommandUpdateAppsLatest.vendorVersion Write-Output "Found DCU Version $DCUVersion" $DCUVersionInstalled = Get-DCUVersion If ($DCUVersionInstalled -ne $false){[Version]$CurrentVersion = $DCUVersionInstalled} Else {[Version]$CurrentVersion = 0.0.0.0} if ($DCUVersion -gt $CurrentVersion){ $DellCabDownloadsPath = $DownloadPath [void][System.IO.Directory]::CreateDirectory($DellCabDownloadsPath) if (!(Test-Path $DellCabExtractPath)){$null = New-Item -Path $DellCabExtractPath -ItemType Directory -Force} $TargetFileName = ($CommandUpdateAppsLatest.path).Split("/") | Select-Object -Last 1 $TargetLink = $CommandUpdateAppsLatest.path $TargetFilePathName = "$($DellCabDownloadsPath)\$($TargetFileName)" if ($UseWebRequest){ Write-Output "Using WebRequest to download the file" Invoke-WebRequest -Uri $TargetLink -OutFile $TargetFilePathName -UseBasicParsing -Verbose } else{ Write-Output "Using BITS to download the file" Start-BitsTransfer -Source $TargetLink -Destination $TargetFilePathName -DisplayName $TargetFileName -Description "Downloading Dell Command Update" -ErrorAction SilentlyContinue } if (!(Test-Path $TargetFilePathName)){ Invoke-WebRequest -Uri $TargetLink -OutFile $TargetFilePathName -UseBasicParsing -Verbose } #Confirm Download if (Test-Path $TargetFilePathName){ $LogFileName = ($TargetFilePathName.replace(".exe",".log")).Replace(".EXE",".log") # The Dell Update Package wrapper only accepts /s, /l=, /e=, /f, /passthrough and /bls. IgnoreOOBE is applied via the registry after install. $Arguments = "/s /l=`"$LogFileName`"" Write-Output "Starting DCU Install" Write-Verbose "DCU installer arguments: $Arguments" write-output "Log file = $LogFileName" $Process = Start-Process "$TargetFilePathName" $Arguments -Wait -PassThru write-output "Update Complete with Exitcode: $($Process.ExitCode)" $ExitInfo = Get-DUPExitInfo -DUPExit $Process.ExitCode if ($ExitInfo){ Write-Output "Exit Status: $($ExitInfo.DisplayName) - $($ExitInfo.Description)" } else{ Write-Output "Exit Status: Unknown - No matching DUP exit code information was found." } if ($Process.ExitCode -eq 4){ if (Test-Path -LiteralPath $LogFileName){ $PrerequisiteMessages = Get-Content -LiteralPath $LogFileName | Where-Object { $_ -match '(?i)(needs to be installed|prerequisite|dependency)' } | ForEach-Object { ($_.Trim() -replace '^\d+:\s*','') } | Select-Object -Unique if ($PrerequisiteMessages){ $PrerequisiteSummary = $PrerequisiteMessages | Where-Object { $_ -match '(?i)needs to be installed' } | Select-Object -First 1 if (-not $PrerequisiteSummary){ $PrerequisiteSummary = $PrerequisiteMessages | Select-Object -First 1 } $PrerequisiteSummary = $PrerequisiteSummary -replace '(?i)^Missing prerequisite:\s*','' Write-Output "Missing prerequisite: $PrerequisiteSummary" $PrereqVersionMatch = [regex]::Match(($PrerequisiteMessages -join "`n"), 'Microsoft \.NET Desktop Runtime\s+(?<Version>\d+\.\d+)') if ($PrereqVersionMatch.Success){ $PrereqVersion = $PrereqVersionMatch.Groups['Version'].Value if ($AutoInstallPreReqs){ Write-Output "Installing missing .NET prerequisite version $PrereqVersion" Install-DCUPreReqDOTNet -BaseVersion $PrereqVersion Write-Output "Retrying DCU installation after installing the prerequisite" $Process = Start-Process "$TargetFilePathName" $Arguments -Wait -PassThru Write-Output "DCU retry completed with Exitcode: $($Process.ExitCode)" $RetryExitInfo = Get-DUPExitInfo -DUPExit $Process.ExitCode if ($RetryExitInfo){ Write-Output "Retry Exit Status: $($RetryExitInfo.DisplayName) - $($RetryExitInfo.Description)" } else{ Write-Output "Retry Exit Status: Unknown - No matching DUP exit code information was found." } } else{ Write-Output "Automatic prerequisite installation is disabled. Use -AutoInstallPreReqs to install it and retry DCU." } } } else{ Write-Output "Missing prerequisite: The installer log did not identify the required prerequisite." } } else{ Write-Output "Missing prerequisite: Installer log not found at $LogFileName" } } If($Process -ne $null -and $Process.ExitCode -eq '2'){ Write-Verbose "Reboot Required" } if ($DCUVersion -ge [version]'5.7.1' -and $Process -and $Process.ExitCode -in @(0, 2)) { Write-Output "DCU $DCUVersion supports OOBE deployment; configuring the IgnoreOOBE registry value." $IgnoreOOBEKey = 'HKLM:\SOFTWARE\DELL\UpdateService\Service\UpdateScheduler' $IgnoreOOBEValue = $null $IgnoreOOBEKind = $null if (Test-Path -LiteralPath $IgnoreOOBEKey) { $IgnoreOOBEValue = Get-ItemPropertyValue -LiteralPath $IgnoreOOBEKey -Name 'IgnoreOOBE' -ErrorAction SilentlyContinue -ErrorVariable IgnoreOOBEReadError 2>$null try { $IgnoreOOBEKind = (Get-Item -LiteralPath $IgnoreOOBEKey).GetValueKind('IgnoreOOBE') } catch { $IgnoreOOBEKind = $null } } if ($IgnoreOOBEValue -ne 1 -or $IgnoreOOBEKind -ne [Microsoft.Win32.RegistryValueKind]::DWord) { Write-Output 'Setting Dell UpdateScheduler\IgnoreOOBE to DWORD 1.' $null = New-Item -Path $IgnoreOOBEKey -Force -ErrorAction Stop if ($null -ne $IgnoreOOBEKind) { Remove-ItemProperty -LiteralPath $IgnoreOOBEKey -Name 'IgnoreOOBE' -Force -ErrorAction SilentlyContinue } $null = New-ItemProperty -LiteralPath $IgnoreOOBEKey -Name 'IgnoreOOBE' -Value 1 -PropertyType DWord -Force -ErrorAction Stop } else { Write-Output 'Dell UpdateScheduler\IgnoreOOBE is already set to DWORD 1.' } $VerifiedIgnoreOOBEValue = Get-ItemPropertyValue -LiteralPath $IgnoreOOBEKey -Name 'IgnoreOOBE' -ErrorAction Stop $VerifiedIgnoreOOBEKind = (Get-Item -LiteralPath $IgnoreOOBEKey).GetValueKind('IgnoreOOBE') if ($VerifiedIgnoreOOBEValue -ne 1 -or $VerifiedIgnoreOOBEKind -ne [Microsoft.Win32.RegistryValueKind]::DWord) { throw 'Dell UpdateScheduler\IgnoreOOBE registry verification failed.' } Write-Output 'Verified Dell UpdateScheduler\IgnoreOOBE is DWORD 1.' } # Dell DUP: 0 = success, 2 = success/reboot required. Everything else failed to install. $FinalExitInfo = Get-DUPExitInfo -DUPExit $Process.ExitCode | Select-Object -First 1 $FinalCodeName = if ($FinalExitInfo) { $FinalExitInfo.DisplayName } else { 'Unknown' } $FinalDescription = if ($FinalExitInfo) { $FinalExitInfo.Description } else { 'No matching DUP exit code information was found.' } $InstallSucceeded = $Process.ExitCode -in @(0, 2) if (-not $InstallSucceeded){ throw "Dell Command Update $DCUVersion install failed with exit code $($Process.ExitCode) ($FinalCodeName - $FinalDescription). Log: $LogFileName" } return [PSCustomObject]@{ Version = $DCUVersion ExitCode = $Process.ExitCode CodeName = $FinalCodeName Description = $FinalDescription LogPath = $LogFileName Success = $true RebootRequired = ($Process.ExitCode -eq 2) } } else{ throw "Failed to download Dell Command Update from $TargetLink" } } else{ Write-Output "Installed DCU: $CurrentVersion, Skipping Install" } } else{ if ($DownloadPathSpecified){ [void][System.IO.Directory]::CreateDirectory($DownloadPath) $TargetFileName = ($CommandUpdateAppsLatest.path).Split("/") | Select-Object -Last 1 $TargetLink = $CommandUpdateAppsLatest.path $TargetFilePathName = Join-Path -Path $DownloadPath -ChildPath $TargetFileName if ($UseWebRequest){ Write-Verbose "Using WebRequest to download the file" Invoke-WebRequest -Uri $TargetLink -OutFile $TargetFilePathName -UseBasicParsing -Verbose } else{ Write-Verbose "Using BITS to download the file" Start-BitsTransfer -Source $TargetLink -Destination $TargetFilePathName -DisplayName $TargetFileName -Description "Downloading Dell Command Update" -ErrorAction SilentlyContinue } if (!(Test-Path $TargetFilePathName)){ Invoke-WebRequest -Uri $TargetLink -OutFile $TargetFilePathName -UseBasicParsing -Verbose } if (Test-Path $TargetFilePathName){ return $TargetFilePathName } Write-Verbose "FAILED TO DOWNLOAD DCU" return } if ($Latest){ Return $CommandUpdateAppsLatest } else{ return $CommandUpdateApps } } } else{ return "No DCU Found" } } |