Public/Intel.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Intel driver management functions .DESCRIPTION Provides detection, installation, and management of Intel drivers. Uses catalog-based approach since Intel DSA has no CLI/API support. .NOTES Intel vendor ID: VEN_8086 Device IDs follow pattern: PCI\VEN_8086&DEV_XXXX #> #region Intel Device Detection function Get-IntelDevices { <# .SYNOPSIS Detects Intel devices on the system .DESCRIPTION Queries Win32_PnPSignedDriver for devices manufactured by Intel. Groups devices by device class (Display, Network, Audio, etc.) .PARAMETER DeviceClass Filter by device class (e.g., 'Display', 'Net', 'Media') .EXAMPLE Get-IntelDevices .EXAMPLE Get-IntelDevices -DeviceClass 'Display' .OUTPUTS Array of Intel device objects with DeviceID, DeviceName, DeviceClass, DriverVersion #> [CmdletBinding()] param( [Parameter()] [string]$DeviceClass ) try { # Query PnP signed drivers for Intel devices # Intel vendor ID is 8086, or Manufacturer contains "Intel" $devices = Get-CimInstance -ClassName Win32_PnPSignedDriver -ErrorAction Stop | Where-Object { if (-not $_.DeviceID) { return $false } # Check for Intel vendor ID (VEN_8086) or Manufacturer contains Intel $isIntel = ($_.DeviceID -match 'VEN_8086') -or ($_.Manufacturer -like '*Intel*') -or ($_.DriverProviderName -like '*Intel*') # Filter by device class if specified if ($DeviceClass -and $isIntel) { return $_.DeviceClass -like "*$DeviceClass*" } return $isIntel } $intelDevices = $devices | ForEach-Object { [PSCustomObject]@{ DeviceID = $_.DeviceID DeviceName = $_.DeviceName DeviceClass = $_.DeviceClass Manufacturer = $_.Manufacturer DriverVersion = $_.DriverVersion DriverDate = $_.DriverDate InfName = $_.InfName DriverProviderName = $_.DriverProviderName IsSigned = $_.IsSigned HardwareID = $_.HardwareID } } Write-DriverLog -Message "Detected $($intelDevices.Count) Intel devices" -Severity Info ` -Context @{ DeviceCount = $intelDevices.Count; DeviceClasses = ($intelDevices.DeviceClass | Sort-Object -Unique) } return $intelDevices } catch { Write-DriverLog -Message "Failed to detect Intel devices: $($_.Exception.Message)" -Severity Error return @() } } #endregion #region Intel Driver Catalog function Get-IntelDriverCatalog { <# .SYNOPSIS Loads the Intel driver catalog from JSON .DESCRIPTION Loads the catalog file from Config/intel_drivers.json .OUTPUTS Hashtable with drivers array #> [CmdletBinding()] param() $catalogPath = Join-Path $script:ModuleRoot "Config\intel_drivers.json" if (-not (Test-Path $catalogPath)) { Write-DriverLog -Message "Intel driver catalog not found: $catalogPath" -Severity Warning return @{ drivers = @() } } try { $catalog = Get-Content -Path $catalogPath -Raw | ConvertFrom-Json return @{ drivers = $catalog.drivers lastUpdated = if ($catalog.lastUpdated) { $catalog.lastUpdated } else { $null } } } catch { Write-DriverLog -Message "Failed to load Intel driver catalog: $($_.Exception.Message)" -Severity Error return @{ drivers = @() } } } function Match-IntelDeviceToCatalog { <# .SYNOPSIS Matches an Intel device to catalog entries .DESCRIPTION Matches device by DeviceID, HardwareID, or device class .PARAMETER Device Intel device object from Get-IntelDevices .PARAMETER Catalog Catalog object from Get-IntelDriverCatalog .OUTPUTS Matching catalog entries #> [CmdletBinding()] param( [Parameter(Mandatory)] [PSCustomObject]$Device, [Parameter(Mandatory)] [hashtable]$Catalog ) $catalogMatches = @() foreach ($driver in $Catalog.drivers) { $isMatch = $false # Match by device IDs if ($driver.deviceIds) { foreach ($deviceId in $driver.deviceIds) { # Support wildcard matching (e.g., PCI\VEN_8086&DEV_*) # Escape special regex characters first, then replace wildcards $escaped = [regex]::Escape($deviceId) $pattern = $escaped -replace '\\\*', '.*' -replace '\\\?', '.' try { if ($Device.DeviceID -match $pattern -or $Device.HardwareID -match $pattern) { $isMatch = $true break } } catch { # Invalid regex pattern - skip this device ID Write-DriverLog -Message "Invalid device ID pattern: $deviceId - $($_.Exception.Message)" -Severity Warning } } } # Match by device class if (-not $isMatch -and $driver.deviceClass -and $Device.DeviceClass) { if ($Device.DeviceClass -like "*$($driver.deviceClass)*") { $isMatch = $true } } if ($isMatch) { $catalogMatches += $driver } } return $catalogMatches } #endregion #region Intel Driver Update Detection function Get-IntelDriverUpdates { <# .SYNOPSIS Scans for available Intel driver updates .DESCRIPTION Compares installed Intel drivers with catalog entries to find updates. Uses catalog-based approach since Intel DSA has no CLI support. .PARAMETER DeviceClass Filter by device class .EXAMPLE Get-IntelDriverUpdates .EXAMPLE Get-IntelDriverUpdates -DeviceClass 'Display' .OUTPUTS Array of available update objects #> [CmdletBinding()] param( [Parameter()] [string]$DeviceClass ) Write-DriverLog -Message "Scanning for Intel driver updates" -Severity Info # Get installed Intel devices $devices = Get-IntelDevices -DeviceClass $DeviceClass if ($devices.Count -eq 0) { Write-DriverLog -Message "No Intel devices detected" -Severity Info return @() } # Load catalog $catalog = Get-IntelDriverCatalog if ($catalog.drivers.Count -eq 0) { Write-DriverLog -Message "Intel driver catalog is empty" -Severity Warning return @() } $updates = @() foreach ($device in $devices) { # Find matching catalog entries $catalogEntries = Match-IntelDeviceToCatalog -Device $device -Catalog $catalog foreach ($entry in $catalogEntries) { # Compare versions $installedVersion = $device.DriverVersion $availableVersion = $entry.driverVersion if (-not $installedVersion -or -not $availableVersion) { continue } # Try version comparison $needsUpdate = $false try { $installed = [version]$installedVersion $available = [version]$availableVersion $needsUpdate = $available -gt $installed } catch { # Fallback to string comparison $needsUpdate = $availableVersion -ne $installedVersion } if ($needsUpdate) { $updates += [PSCustomObject]@{ DeviceID = $device.DeviceID DeviceName = $device.DeviceName DeviceClass = $device.DeviceClass InstalledVersion = $installedVersion AvailableVersion = $availableVersion DownloadUrl = $entry.downloadUrl ReleaseDate = $entry.releaseDate Severity = if ($entry.severity) { $entry.severity } else { 'Recommended' } Description = if ($entry.description) { $entry.description } else { "Intel $($device.DeviceClass) Driver Update" } CatalogEntry = $entry } } } } Write-DriverLog -Message "Found $($updates.Count) Intel driver updates" -Severity Info ` -Context @{ Updates = ($updates | Select-Object DeviceName, InstalledVersion, AvailableVersion) } return $updates } #endregion #region Intel Driver Installation function Install-IntelDriverUpdates { <# .SYNOPSIS Installs Intel driver updates .DESCRIPTION Downloads and installs Intel driver updates from catalog URLs. Creates driver snapshot before installation for rollback capability. .PARAMETER DeviceClass Filter by device class (only install updates for specific class) .PARAMETER NoReboot Suppress automatic reboot .PARAMETER Force Force installation even if version check fails .EXAMPLE Install-IntelDriverUpdates .EXAMPLE Install-IntelDriverUpdates -DeviceClass 'Display' -NoReboot .OUTPUTS DriverUpdateResult object #> [CmdletBinding(SupportsShouldProcess)] [OutputType('DriverUpdateResult')] param( [Parameter()] [string]$DeviceClass, [Parameter()] [switch]$NoReboot, [Parameter()] [switch]$Force ) Assert-Elevation -Operation "Installing Intel drivers" $result = [DriverUpdateResult]::new() $result.CorrelationId = $script:CorrelationId # Get available updates $updates = Get-IntelDriverUpdates -DeviceClass $DeviceClass if ($updates.Count -eq 0) { $result.Success = $true $result.Message = "No Intel driver updates available" $result.ExitCode = 0 Write-DriverLog -Message $result.Message -Severity Info return $result } # Create driver snapshot before installation try { $snapshotName = "Pre-Intel-Update-$(Get-Date -Format 'yyyyMMdd_HHmmss')" Write-DriverLog -Message "Creating driver snapshot: $snapshotName" -Severity Info $snapshot = New-DriverSnapshot -Name $snapshotName -IncludeInfFiles $result.Details['PreUpdateSnapshot'] = $snapshot.ID } catch { Write-DriverLog -Message "Failed to create snapshot: $($_.Exception.Message)" -Severity Warning if (-not $Force) { $result.Success = $false $result.Message = "Failed to create driver snapshot - aborting (use -Force to override)" $result.ExitCode = 1 return $result } } if ($PSCmdlet.ShouldProcess("$($updates.Count) Intel driver updates", "Install")) { $installed = 0 $failed = 0 $rebootRequired = $false foreach ($update in $updates) { Write-DriverLog -Message "Installing: $($update.DeviceName) ($($update.InstalledVersion) -> $($update.AvailableVersion))" -Severity Info try { # Download driver $tempPath = Join-Path $env:TEMP "IntelDriver_$(Get-Random)" New-Item -Path $tempPath -ItemType Directory -Force | Out-Null $driverFile = Join-Path $tempPath (Split-Path $update.DownloadUrl -Leaf) Write-DriverLog -Message "Downloading from: $($update.DownloadUrl)" -Severity Info try { Invoke-WebRequest -Uri $update.DownloadUrl -OutFile $driverFile -UseBasicParsing -ErrorAction Stop } catch { # Try with certificate validation bypass for some Intel URLs $originalCertPolicy = [System.Net.ServicePointManager]::ServerCertificateValidationCallback [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } try { Invoke-WebRequest -Uri $update.DownloadUrl -OutFile $driverFile -UseBasicParsing -ErrorAction Stop } finally { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $originalCertPolicy } } # Extract if it's a ZIP if ($driverFile -match '\.zip$') { $extractPath = Join-Path $tempPath "extracted" Expand-Archive -Path $driverFile -DestinationPath $extractPath -Force # Find INF file or installer $infFiles = Get-ChildItem -Path $extractPath -Filter "*.inf" -Recurse -ErrorAction SilentlyContinue $installerExe = Get-ChildItem -Path $extractPath -Filter "*.exe" -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'setup|install|driver' } | Select-Object -First 1 if ($infFiles) { # Install via pnputil foreach ($infFile in $infFiles) { $pnputilResult = & pnputil /add-driver "$($infFile.FullName)" /install 2>&1 if ($LASTEXITCODE -eq 0) { $installed++ Write-DriverLog -Message "Installed via pnputil: $($infFile.Name)" -Severity Info } else { $failed++ Write-DriverLog -Message "pnputil failed for $($infFile.Name): exit $LASTEXITCODE" -Severity Warning } } } elseif ($installerExe) { # Run installer silently $installArgs = @('/S', '/SILENT', '/VERYSILENT', '/quiet', '/qn') $installResult = Start-Process -FilePath $installerExe.FullName -ArgumentList $installArgs -Wait -PassThru -NoNewWindow if ($installResult.ExitCode -eq 0 -or $installResult.ExitCode -eq 3010) { $installed++ if ($installResult.ExitCode -eq 3010) { $rebootRequired = $true } Write-DriverLog -Message "Installer completed: exit $($installResult.ExitCode)" -Severity Info } else { $failed++ Write-DriverLog -Message "Installer failed: exit $($installResult.ExitCode)" -Severity Warning } } else { Write-DriverLog -Message "No INF or installer found in driver package" -Severity Warning $failed++ } } elseif ($driverFile -match '\.exe$') { # Direct installer $installArgs = @('/S', '/SILENT', '/VERYSILENT', '/quiet', '/qn') $installResult = Start-Process -FilePath $driverFile -ArgumentList $installArgs -Wait -PassThru -NoNewWindow if ($installResult.ExitCode -eq 0 -or $installResult.ExitCode -eq 3010) { $installed++ if ($installResult.ExitCode -eq 3010) { $rebootRequired = $true } } else { $failed++ } } else { Write-DriverLog -Message "Unsupported driver file format: $driverFile" -Severity Warning $failed++ } # Cleanup Remove-Item -Path $tempPath -Recurse -Force -ErrorAction SilentlyContinue } catch { $failed++ Write-DriverLog -Message "Failed to install $($update.DeviceName): $($_.Exception.Message)" -Severity Error } } $result.Success = ($failed -eq 0) $result.Message = "Installed $installed Intel driver updates" if ($failed -gt 0) { $result.Message += ", $failed failed" } $result.UpdatesApplied = $installed $result.UpdatesFailed = $failed $result.RebootRequired = $rebootRequired -and (-not $NoReboot) $result.ExitCode = if ($result.RebootRequired) { 3010 } elseif ($result.Success) { 0 } else { 1 } Write-DriverLog -Message $result.Message -Severity Info -Context $result.ToHashtable() } return $result } #endregion #region Intel Module Initialization function Initialize-IntelModule { <# .SYNOPSIS Initializes Intel driver management .DESCRIPTION Checks for Intel devices, loads catalog, and validates configuration. .OUTPUTS PSCustomObject with initialization status #> [CmdletBinding()] param() $status = [PSCustomObject]@{ Initialized = $false DevicesDetected = 0 CatalogLoaded = $false CatalogPath = $null Message = "" } # Detect Intel devices $devices = Get-IntelDevices $status.DevicesDetected = $devices.Count # Load catalog $catalogPath = Join-Path $script:ModuleRoot "Config\intel_drivers.json" $status.CatalogPath = $catalogPath if (Test-Path $catalogPath) { $catalog = Get-IntelDriverCatalog $status.CatalogLoaded = ($catalog.drivers.Count -gt 0) if ($status.CatalogLoaded) { $status.Message = "Intel module initialized: $($status.DevicesDetected) devices, $($catalog.drivers.Count) catalog entries" } else { $status.Message = "Intel module initialized: $($status.DevicesDetected) devices, but catalog is empty" } } else { $status.Message = "Intel module initialized: $($status.DevicesDetected) devices, but catalog not found at $catalogPath" } $status.Initialized = $true Write-DriverLog -Message $status.Message -Severity Info -Context $status return $status } #endregion |