Public/Dell.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Dell driver management functions #> function Get-DellCommandUpdatePath { <# .SYNOPSIS Finds the Dell Command Update CLI executable .OUTPUTS Path to dcu-cli.exe or $null if not found #> [CmdletBinding()] param() $paths = @( "${env:ProgramFiles}\Dell\CommandUpdate\dcu-cli.exe", "${env:ProgramFiles(x86)}\Dell\CommandUpdate\dcu-cli.exe" ) return $paths | Where-Object { Test-Path $_ } | Select-Object -First 1 } function Install-DellCommandUpdate { <# .SYNOPSIS Downloads and installs Dell Command Update .DESCRIPTION Automatically downloads the latest Dell Command Update from Dell's website and performs a silent installation. Requires elevation. .EXAMPLE Install-DellCommandUpdate .NOTES Dell Command Update Universal Windows Platform application https://www.dell.com/support/kbdoc/en-us/000177325/dell-command-update #> [CmdletBinding()] param() Assert-Elevation -Operation "Installing Dell Command Update" $config = $script:ModuleConfig # Dell Command Update download URL (Universal Windows Platform version) # Priority: 1) Environment variable, 2) Module config, 3) Default URL $dcuUrl = if ($env:PSDM_DCU_URL) { Write-DriverLog -Message "Using DCU URL from environment variable" -Severity Info $env:PSDM_DCU_URL } elseif ($config.DellCommandUpdateUrl) { $config.DellCommandUpdateUrl } else { # Default URL for DCU 5.x Universal Windows Platform "https://dl.dell.com/FOLDER11914155M/1/Dell-Command-Update-Windows-Universal-Application_601KT_WIN_5.4.0_A00.EXE" } $installerPath = Join-Path $env:TEMP "DellCommandUpdate_$(Get-Date -Format 'yyyyMMddHHmmss').exe" Write-DriverLog -Message "Downloading Dell Command Update from $dcuUrl" -Severity Info try { # Download with retry logic Invoke-WithRetry -ScriptBlock { # Use BITS for reliable download, fallback to WebRequest try { Start-BitsTransfer -Source $dcuUrl -Destination $installerPath -ErrorAction Stop } catch { Invoke-WebRequest -Uri $dcuUrl -OutFile $installerPath -UseBasicParsing -ErrorAction Stop } } -MaxAttempts 3 -ExponentialBackoff if (-not (Test-Path $installerPath)) { throw "Download failed - installer not found" } $fileSize = (Get-Item $installerPath).Length / 1MB Write-DriverLog -Message "Downloaded DCU installer ($([math]::Round($fileSize, 1)) MB)" -Severity Info # Silent install Write-DriverLog -Message "Installing Dell Command Update silently..." -Severity Info $installProcess = Start-Process -FilePath $installerPath -ArgumentList "/s" -Wait -PassThru -NoNewWindow if ($installProcess.ExitCode -eq 0) { Write-DriverLog -Message "Dell Command Update installed successfully" -Severity Info } else { throw "Installation failed with exit code: $($installProcess.ExitCode)" } } catch { Write-DriverLog -Message "Failed to install Dell Command Update: $($_.Exception.Message)" -Severity Error throw } finally { # Cleanup installer if (Test-Path $installerPath) { Remove-Item $installerPath -Force -ErrorAction SilentlyContinue } } } function Initialize-DellModule { <# .SYNOPSIS Ensures Dell Command Update is available .DESCRIPTION Checks if Dell Command Update is installed. If not, automatically downloads and installs it from Dell's website. .OUTPUTS Path to dcu-cli.exe .EXAMPLE $dcuPath = Initialize-DellModule #> [CmdletBinding()] param() $dcuPath = Get-DellCommandUpdatePath if (-not $dcuPath) { Write-DriverLog -Message "Dell Command Update not found, installing..." -Severity Info try { Install-DellCommandUpdate # Wait a moment for installation to complete Start-Sleep -Seconds 2 # Re-check for DCU $dcuPath = Get-DellCommandUpdatePath if (-not $dcuPath) { throw "Dell Command Update installation completed but dcu-cli.exe not found" } Write-DriverLog -Message "Dell Command Update ready at: $dcuPath" -Severity Info } catch { Write-DriverLog -Message "Failed to initialize Dell Command Update: $($_.Exception.Message)" -Severity Error throw "Dell Command Update could not be installed: $($_.Exception.Message)" } } return $dcuPath } function Get-DellDriverUpdates { <# .SYNOPSIS Scans for available Dell driver updates .DESCRIPTION Uses Dell Command Update to scan for applicable updates .PARAMETER UpdateTypes Types of updates to scan for: Driver, BIOS, Firmware, All .PARAMETER Severity Severity levels: Critical, Recommended, Optional .EXAMPLE Get-DellDriverUpdates -UpdateTypes Driver -Severity Critical, Recommended .OUTPUTS Array of available update objects #> [CmdletBinding()] param( [Parameter()] [ValidateSet('Driver', 'BIOS', 'Firmware', 'All')] [string[]]$UpdateTypes = @('Driver'), [Parameter()] [ValidateSet('Critical', 'Recommended', 'Optional')] [string[]]$Severity = @('Critical', 'Recommended') ) try { $dcuCli = Initialize-DellModule } catch { Write-DriverLog -Message "Dell Command Update not available: $($_.Exception.Message)" -Severity Warning return @() } $reportPath = "$env:ProgramData\Dell\UpdateScan" if (-not (Test-Path $reportPath)) { New-Item -Path $reportPath -ItemType Directory -Force | Out-Null } Write-DriverLog -Message "Scanning for Dell updates" -Severity Info # Run scan $scanArgs = @('/scan', '-silent', "-report=$reportPath") $scanResult = & $dcuCli @scanArgs 2>&1 $scanExitCode = $LASTEXITCODE # Parse results $xmlPath = Join-Path $reportPath "DCUApplicableUpdates.xml" if (-not (Test-Path $xmlPath)) { Write-DriverLog -Message "No updates report generated" -Severity Info return @() } [xml]$updatesXml = Get-Content $xmlPath $updates = $updatesXml.updates.update | Where-Object { $typeMatch = switch ($_.type) { 'Driver' { 'Driver' -in $UpdateTypes -or 'All' -in $UpdateTypes } 'BIOS' { 'BIOS' -in $UpdateTypes -or 'All' -in $UpdateTypes } 'Firmware' { 'Firmware' -in $UpdateTypes -or 'All' -in $UpdateTypes } default { 'All' -in $UpdateTypes } } $typeMatch } | ForEach-Object { [PSCustomObject]@{ Name = $_.name Version = $_.version Type = $_.type Category = $_.category Urgency = $_.urgency ReleaseDate = $_.date Size = $_.size Description = $_.description } } Write-DriverLog -Message "Found $($updates.Count) Dell updates" -Severity Info ` -Context @{ Updates = ($updates | Select-Object Name, Version, Type) } return $updates } function Install-DellDriverUpdates { <# .SYNOPSIS Installs Dell driver updates .DESCRIPTION Uses Dell Command Update to install applicable updates .PARAMETER UpdateTypes Types of updates to install .PARAMETER Severity Severity levels to include .PARAMETER NoReboot Suppress automatic reboot .EXAMPLE Install-DellDriverUpdates -UpdateTypes Driver -NoReboot .OUTPUTS DriverUpdateResult object #> [CmdletBinding(SupportsShouldProcess)] [OutputType('DriverUpdateResult')] param( [Parameter()] [ValidateSet('Driver', 'BIOS', 'Firmware', 'All')] [string[]]$UpdateTypes = @('Driver'), [Parameter()] [ValidateSet('Critical', 'Recommended', 'Optional')] [string[]]$Severity = @('Critical', 'Recommended'), [Parameter()] [switch]$NoReboot ) Assert-Elevation -Operation "Installing Dell drivers" $result = [DriverUpdateResult]::new() $result.CorrelationId = $script:CorrelationId try { $dcuCli = Initialize-DellModule } catch { $result.Success = $false $result.Message = "Dell Command Update not available: $($_.Exception.Message)" $result.ExitCode = 1 Write-DriverLog -Message $result.Message -Severity Error return $result } # Configure DCU for silent operation $configArgs = @('/configure', '-userConsent=disable', '-autoSuspendBitLocker=enable', '-silent') & $dcuCli @configArgs 2>&1 | Out-Null # Map update types $typeParam = ($UpdateTypes | ForEach-Object { $_.ToLower() }) -join ',' if ('All' -in $UpdateTypes) { $typeParam = 'driver,bios,firmware,application' } # Build apply command $applyArgs = @( '/applyUpdates' "-updateType=$typeParam" '-updateSeverity=security,critical,recommended' '-autoSuspendBitLocker=enable' '-silent' "-outputLog=$env:ProgramData\Dell\Logs\DCU_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" ) if ($NoReboot) { $applyArgs += '-reboot=disable' } if ($PSCmdlet.ShouldProcess("Dell drivers", "Install updates")) { Write-DriverLog -Message "Installing Dell updates: $typeParam" -Severity Info $applyResult = & $dcuCli @applyArgs 2>&1 $exitCode = $LASTEXITCODE # Interpret exit codes switch ($exitCode) { 0 { $result.Success = $true $result.Message = "Updates applied successfully" $result.RebootRequired = $false } 1 { $result.Success = $true $result.Message = "Updates applied - reboot required" $result.RebootRequired = $true } 500 { $result.Success = $true $result.Message = "No applicable updates" $result.RebootRequired = $false } default { $result.Success = $false $result.Message = "DCU error code: $exitCode" $result.RebootRequired = $false } } $result.ExitCode = if ($result.RebootRequired) { 3010 } elseif ($result.Success) { 0 } else { 1 } Write-DriverLog -Message "Dell update complete: $($result.Message)" -Severity Info ` -Context $result.ToHashtable() } return $result } function Install-DellFullDriverPack { <# .SYNOPSIS Installs the complete Dell driver pack .DESCRIPTION Performs a full driver reinstallation using Dell Command Update .PARAMETER NoReboot Suppress automatic reboot .EXAMPLE Install-DellFullDriverPack -NoReboot #> [CmdletBinding(SupportsShouldProcess)] [OutputType('DriverUpdateResult')] param( [Parameter()] [switch]$NoReboot ) Assert-Elevation -Operation "Installing Dell full driver pack" $result = [DriverUpdateResult]::new() $result.CorrelationId = $script:CorrelationId try { $dcuCli = Initialize-DellModule } catch { $result.Success = $false $result.Message = "Dell Command Update not available: $($_.Exception.Message)" $result.ExitCode = 1 Write-DriverLog -Message $result.Message -Severity Error return $result } if ($PSCmdlet.ShouldProcess("Dell full driver pack", "Install")) { Write-DriverLog -Message "Starting Dell full driver pack install" -Severity Info $installArgs = @( '/driverInstall' '-autoSuspendBitLocker=enable' '-silent' ) if ($NoReboot) { $installArgs += '-reboot=disable' } & $dcuCli @installArgs 2>&1 | Out-Null $exitCode = $LASTEXITCODE $result.Success = $exitCode -in @(0, 1, 500) $result.Message = "Full pack install completed with exit code: $exitCode" $result.RebootRequired = $exitCode -eq 1 $result.ExitCode = if ($exitCode -eq 1) { 3010 } elseif ($exitCode -in @(0, 500)) { 0 } else { 1 } Write-DriverLog -Message $result.Message -Severity Info -Context $result.ToHashtable() } return $result } |