fix single driver install issues

This commit is contained in:
Chris Titus
2026-02-25 16:59:44 -06:00
parent 18594f6d2d
commit d0012449ad

View File

@@ -80,47 +80,48 @@ function Invoke-WinUtilISOScript {
} }
} }
# Returns the full paths of every exported .inf whose online driver class # Copies driver package folders (one per exported .inf) whose online class
# matches one of the supplied class names. # matches any of the supplied class names into a new temp staging directory.
function Get-ExportedInfPaths { # Returns the staging directory path — caller must delete it when done.
# Using a staging dir lets DISM inject all drivers in a single /Recurse
# call instead of one DISM process launch per .inf file.
function New-DriverStagingDir {
param ([string]$ExportRoot, [string[]]$Classes) param ([string]$ExportRoot, [string[]]$Classes)
$stagingDir = Join-Path $env:TEMP "WinUtil_DriverStage_$(Get-Random)"
New-Item -Path $stagingDir -ItemType Directory -Force | Out-Null
Get-WindowsDriver -Online | Get-WindowsDriver -Online |
Where-Object { $_.ClassName -in $Classes } | Where-Object { $_.ClassName -in $Classes } |
ForEach-Object { [IO.Path]::GetFileNameWithoutExtension($_.OriginalFileName) } | ForEach-Object { [IO.Path]::GetFileNameWithoutExtension($_.OriginalFileName) } |
Select-Object -Unique | Select-Object -Unique |
ForEach-Object { ForEach-Object {
Get-ChildItem -Path $ExportRoot -Filter "$_.inf" -Recurse -ErrorAction SilentlyContinue | Get-ChildItem -Path $ExportRoot -Filter "$_.inf" -Recurse -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty FullName Select-Object -ExpandProperty DirectoryName -Unique |
ForEach-Object {
# Each exported driver lives in its own sub-folder;
# copy that folder (with its binary files) into staging.
$dest = Join-Path $stagingDir (Split-Path $_ -Leaf)
Copy-Item -Path $_ -Destination $dest -Recurse -Force -ErrorAction SilentlyContinue
}
} }
return $stagingDir
} }
# Injects drivers into a DISM-mounted image. Pass either a list of .inf # Injects all drivers from $DriverDir into a DISM-mounted image in one call.
# paths via -InfPaths, or a driver folder via -DriverDir (uses /Recurse).
function Add-DriversToImage { function Add-DriversToImage {
param ( param (
[string]$MountPath, [string]$MountPath,
[string[]]$InfPaths,
[string]$DriverDir, [string]$DriverDir,
[string]$Label = "image", [string]$Label = "image",
[scriptblock]$Logger [scriptblock]$Logger
) )
if ($DriverDir) { & dism /English "/image:$MountPath" /Add-Driver "/Driver:$DriverDir" /Recurse 2>&1 |
& dism /English "/image:$MountPath" /Add-Driver "/Driver:$DriverDir" /Recurse 2>&1 | ForEach-Object { & $Logger " dism[$Label]: $_" }
ForEach-Object { & $Logger " dism[$Label]: $_" }
} else {
foreach ($inf in $InfPaths) {
& dism /English "/image:$MountPath" /Add-Driver "/Driver:$inf" 2>&1 |
ForEach-Object { & $Logger " dism[$Label]: $_" }
}
}
} }
# Mounts boot.wim index 2, injects drivers, saves, and dismounts. # Mounts boot.wim index 2, injects all drivers from $DriverDir, saves, dismounts.
# Pass either -InfPaths (individual .inf files) or -DriverDir (/Recurse).
function Invoke-BootWimInject { function Invoke-BootWimInject {
param ( param (
[string]$BootWimPath, [string]$BootWimPath,
[string[]]$InfPaths,
[string]$DriverDir, [string]$DriverDir,
[scriptblock]$Logger [scriptblock]$Logger
) )
@@ -130,7 +131,7 @@ function Invoke-WinUtilISOScript {
try { try {
& $Logger "Mounting boot.wim (index 2 — Windows Setup) for driver injection..." & $Logger "Mounting boot.wim (index 2 — Windows Setup) for driver injection..."
Mount-WindowsImage -ImagePath $BootWimPath -Index 2 -Path $mountDir -ErrorAction Stop | Out-Null Mount-WindowsImage -ImagePath $BootWimPath -Index 2 -Path $mountDir -ErrorAction Stop | Out-Null
Add-DriversToImage -MountPath $mountDir -InfPaths $InfPaths -DriverDir $DriverDir -Label "boot" -Logger $Logger Add-DriversToImage -MountPath $mountDir -DriverDir $DriverDir -Label "boot" -Logger $Logger
& $Logger "Saving boot.wim..." & $Logger "Saving boot.wim..."
Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null
& $Logger "boot.wim driver injection complete." & $Logger "boot.wim driver injection complete."
@@ -219,19 +220,22 @@ function Invoke-WinUtilISOScript {
try { try {
Export-WindowsDriver -Online -Destination $driverExportRoot | Out-Null Export-WindowsDriver -Online -Destination $driverExportRoot | Out-Null
# Stage matching driver folders then do a single DISM /Recurse call.
# install.wim: SCSIAdapter + HIDClass + Net # install.wim: SCSIAdapter + HIDClass + Net
$installInfs = Get-ExportedInfPaths -ExportRoot $driverExportRoot -Classes @('SCSIAdapter','HIDClass','Net') $installStage = New-DriverStagingDir -ExportRoot $driverExportRoot -Classes @('SCSIAdapter','HIDClass','Net')
& $Log "Injecting $(@($installInfs).Count) driver package(s) into install.wim..." & $Log "Injecting staged drivers into install.wim (single DISM call)..."
Add-DriversToImage -MountPath $ScratchDir -InfPaths $installInfs -Label "install" -Logger $Log Add-DriversToImage -MountPath $ScratchDir -DriverDir $installStage -Label "install" -Logger $Log
Remove-Item -Path $installStage -Recurse -Force -ErrorAction SilentlyContinue
& $Log "install.wim driver injection complete." & $Log "install.wim driver injection complete."
# boot.wim: SCSIAdapter + Net only (HID not needed in WinPE) # boot.wim: SCSIAdapter + Net only (HID not needed in WinPE)
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) { if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
$bootWim = Join-Path $ISOContentsDir "sources\boot.wim" $bootWim = Join-Path $ISOContentsDir "sources\boot.wim"
if (Test-Path $bootWim) { if (Test-Path $bootWim) {
$bootInfs = Get-ExportedInfPaths -ExportRoot $driverExportRoot -Classes @('SCSIAdapter','Net') $bootStage = New-DriverStagingDir -ExportRoot $driverExportRoot -Classes @('SCSIAdapter','Net')
& $Log "Injecting $(@($bootInfs).Count) driver package(s) into boot.wim..." & $Log "Injecting staged drivers into boot.wim (single DISM call)..."
Invoke-BootWimInject -BootWimPath $bootWim -InfPaths $bootInfs -Logger $Log Invoke-BootWimInject -BootWimPath $bootWim -DriverDir $bootStage -Logger $Log
Remove-Item -Path $bootStage -Recurse -Force -ErrorAction SilentlyContinue
} else { } else {
& $Log "Warning: boot.wim not found — skipping boot.wim driver injection." & $Log "Warning: boot.wim not found — skipping boot.wim driver injection."
} }