mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-10-08 11:39:10 +11:00
fix(win11creator): drop extension-class driver filter (#5058)
This commit is contained in:
@@ -67,7 +67,7 @@ Then click **Run Windows ISO Modification and Creator** to start the customizati
|
||||
- **Disable Copilot and search box suggestions**
|
||||
|
||||
**Optional: Driver Injection**
|
||||
- If enabled, WinUtil exports the drivers from your current system, stages boot-storage drivers for Windows Setup, and injects eligible packages into the selected `install.wim` image. Extension-class packages and stale duplicates are excluded. Each remaining package is added separately, so one incompatible package does not stop the others. If a package fails, WinUtil discards the partial mount and retries the remaining packages against the original image. Check the live log for warnings: if every package fails, WinUtil keeps the original `install.wim` and still produces the ISO.
|
||||
- If enabled, WinUtil exports the drivers from your current system, stages boot-storage drivers for Windows Setup, and injects eligible packages into the selected `install.wim` image. Stale duplicate packages are excluded before injection. Each remaining package is added separately, so one incompatible package does not stop the others. If a package fails, WinUtil discards the partial mount and retries the remaining packages against the original image. Check the live log for warnings: if every package fails, WinUtil keeps the original `install.wim` and still produces the ISO.
|
||||
|
||||
A live log shows progress as each step completes. This stage usually takes **10–30 minutes** depending on disk speed. The WIM dismount near the end is the slowest part, so do not close WinUtil while it is running.
|
||||
|
||||
|
||||
@@ -84,17 +84,6 @@ function Invoke-WinUtilISOScript {
|
||||
}
|
||||
}
|
||||
|
||||
function Test-WinUtilISODriverExtensionClass {
|
||||
param ([Parameter(Mandatory)][System.IO.FileInfo]$InfFile)
|
||||
|
||||
try {
|
||||
return (Get-Content -LiteralPath $InfFile.FullName -Raw -ErrorAction Stop) -match '(?im)^\s*Class\s*=\s*"?Extension"?\s*(?:;.*)?$'
|
||||
} catch {
|
||||
$null = & $Logger "Warning: could not classify driver '$($InfFile.FullName)': $_"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Get-WinUtilISODriverPackageVersion {
|
||||
param ([Parameter(Mandatory)][System.IO.FileInfo]$InfFile)
|
||||
|
||||
@@ -160,15 +149,6 @@ function Invoke-WinUtilISOScript {
|
||||
|
||||
foreach ($driverFolderGroup in $DriverFolderGroups) {
|
||||
$driverFolder = [string]$driverFolderGroup.Name
|
||||
$isExtension = [bool]@($driverFolderGroup.Group | Where-Object { Test-WinUtilISODriverExtensionClass -InfFile $_ }).Count
|
||||
|
||||
if ($isExtension) {
|
||||
# $null = discards $Logger's own output; this function's return value is captured
|
||||
# by the caller, and an emitting logger (e.g. this function's own default) would
|
||||
# otherwise leak into the surviving-folder list.
|
||||
$null = & $Logger "Excluding extension-class driver package '$driverFolder' from Add-Driver (Class=Extension is not a serviceable hardware driver)."
|
||||
continue
|
||||
}
|
||||
|
||||
# DISM names exported package folders <infname>_<arch>_<hash>; grouping on infname+arch
|
||||
# (dropping the hash) is what lets us recognize two exports of the same driver. When a
|
||||
@@ -346,103 +326,97 @@ function Invoke-WinUtilISOScript {
|
||||
$metadataBefore = Get-WinUtilISOWimMetadata -ImagePath $InstallImagePath -Index $InstallImageIndex
|
||||
Assert-WinUtilISOWimMetadata -Before $metadataBefore
|
||||
|
||||
if ($stagedDriverFolders.Count -eq 0) {
|
||||
# Nothing safe to inject (e.g. every exported package was an Extension-class add-on)
|
||||
# isn't a failure: leave install.wim untouched and continue building the ISO.
|
||||
& $Logger 'No drivers found to inject: every exported package was excluded (Extension class or stale duplicate). Skipping driver injection; install.wim is unchanged.'
|
||||
} else {
|
||||
$excludedDriverFolderGroups = @($driverFolders | Where-Object { $_.Name -notin $stagedDriverFolders })
|
||||
foreach ($excludedDriverFolderGroup in $excludedDriverFolderGroups) {
|
||||
$excludedFolder = [string]$excludedDriverFolderGroup.Name
|
||||
$hasRetainedDescendant = [bool]@($stagedDriverFolders | Where-Object {
|
||||
$_.StartsWith("$excludedFolder\", [System.StringComparison]::OrdinalIgnoreCase)
|
||||
}).Count
|
||||
if ($hasRetainedDescendant) {
|
||||
try {
|
||||
foreach ($excludedInf in $excludedDriverFolderGroup.Group) {
|
||||
Remove-Item -LiteralPath $excludedInf.FullName -Force -ErrorAction Stop
|
||||
}
|
||||
} catch {
|
||||
throw "Failed to remove excluded driver INF files from package '$excludedFolder' before injection: $_"
|
||||
$excludedDriverFolderGroups = @($driverFolders | Where-Object { $_.Name -notin $stagedDriverFolders })
|
||||
foreach ($excludedDriverFolderGroup in $excludedDriverFolderGroups) {
|
||||
$excludedFolder = [string]$excludedDriverFolderGroup.Name
|
||||
$hasRetainedDescendant = [bool]@($stagedDriverFolders | Where-Object {
|
||||
$_.StartsWith("$excludedFolder\", [System.StringComparison]::OrdinalIgnoreCase)
|
||||
}).Count
|
||||
if ($hasRetainedDescendant) {
|
||||
try {
|
||||
foreach ($excludedInf in $excludedDriverFolderGroup.Group) {
|
||||
Remove-Item -LiteralPath $excludedInf.FullName -Force -ErrorAction Stop
|
||||
}
|
||||
} catch {
|
||||
throw "Failed to remove excluded driver INF files from package '$excludedFolder' before injection: $_"
|
||||
}
|
||||
|
||||
& $Logger "Keeping excluded driver package directory '$excludedFolder' because it contains a retained nested package, after removing its excluded INF files."
|
||||
continue
|
||||
& $Logger "Keeping excluded driver package directory '$excludedFolder' because it contains a retained nested package, after removing its excluded INF files."
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
Remove-Item -LiteralPath $excludedFolder -Recurse -Force -ErrorAction Stop
|
||||
} catch {
|
||||
throw "Failed to remove excluded driver package '$excludedFolder' before injection: $_"
|
||||
}
|
||||
}
|
||||
|
||||
& $Logger "Exported $($stagedDriverFolders.Count) of $($driverFolders.Count) driver packages ($storageCount staged for WinPE, $($excludedDriverFolderGroups.Count) excluded)."
|
||||
|
||||
Set-ItemProperty -LiteralPath $InstallImagePath -Name IsReadOnly -Value $false
|
||||
New-Item -Path $mountDir -ItemType Directory -Force | Out-Null
|
||||
|
||||
# Add each package separately so one bad driver cannot fail the rest. Because
|
||||
# /Recurse covers descendants, only the highest surviving folder in each tree
|
||||
# needs its own DISM call.
|
||||
$rootPackageFolders = @($stagedDriverFolders | Where-Object {
|
||||
$candidate = $_
|
||||
-not ($stagedDriverFolders | Where-Object { $candidate.StartsWith("$_\", [System.StringComparison]::OrdinalIgnoreCase) })
|
||||
})
|
||||
|
||||
& $Logger "Adding $($rootPackageFolders.Count) root driver packages to install.wim."
|
||||
$remainingDriverFolders = @($rootPackageFolders)
|
||||
while ($remainingDriverFolders.Count -gt 0) {
|
||||
& $Logger "Mounting install.wim index $InstallImageIndex for driver injection..."
|
||||
Invoke-WinUtilISODism -Arguments @('/English', '/Mount-Image', "/ImageFile:$InstallImagePath", "/Index:$InstallImageIndex", "/MountDir:$mountDir") -Operation 'mount' | Out-Null
|
||||
$imageMounted = $true
|
||||
|
||||
$failedDriverFolder = $null
|
||||
foreach ($driverFolder in $remainingDriverFolders) {
|
||||
$driverName = $driverFolder
|
||||
if ($driverFolder.StartsWith($driverExportRoot, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
$driverName = $driverFolder.Substring($driverExportRoot.Length).TrimStart('\')
|
||||
}
|
||||
|
||||
try {
|
||||
Remove-Item -LiteralPath $excludedFolder -Recurse -Force -ErrorAction Stop
|
||||
Invoke-WinUtilISODism -Arguments @('/English', "/Image:$mountDir", '/Add-Driver', "/Driver:$driverFolder", '/Recurse') -Operation "add-driver:$driverName" | Out-Null
|
||||
} catch {
|
||||
throw "Failed to remove excluded driver package '$excludedFolder' before injection: $_"
|
||||
}
|
||||
}
|
||||
|
||||
& $Logger "Exported $($stagedDriverFolders.Count) of $($driverFolders.Count) driver packages ($storageCount staged for WinPE, $($excludedDriverFolderGroups.Count) excluded)."
|
||||
|
||||
Set-ItemProperty -LiteralPath $InstallImagePath -Name IsReadOnly -Value $false
|
||||
New-Item -Path $mountDir -ItemType Directory -Force | Out-Null
|
||||
|
||||
# Add each package separately so one bad driver cannot fail the rest. Because
|
||||
# /Recurse covers descendants, only the highest surviving folder in each tree
|
||||
# needs its own DISM call.
|
||||
$rootPackageFolders = @($stagedDriverFolders | Where-Object {
|
||||
$candidate = $_
|
||||
-not ($stagedDriverFolders | Where-Object { $candidate.StartsWith("$_\", [System.StringComparison]::OrdinalIgnoreCase) })
|
||||
})
|
||||
|
||||
& $Logger "Adding $($rootPackageFolders.Count) root driver packages to install.wim."
|
||||
$remainingDriverFolders = @($rootPackageFolders)
|
||||
while ($remainingDriverFolders.Count -gt 0) {
|
||||
& $Logger "Mounting install.wim index $InstallImageIndex for driver injection..."
|
||||
Invoke-WinUtilISODism -Arguments @('/English', '/Mount-Image', "/ImageFile:$InstallImagePath", "/Index:$InstallImageIndex", "/MountDir:$mountDir") -Operation 'mount' | Out-Null
|
||||
$imageMounted = $true
|
||||
|
||||
$failedDriverFolder = $null
|
||||
foreach ($driverFolder in $remainingDriverFolders) {
|
||||
$driverName = $driverFolder
|
||||
if ($driverFolder.StartsWith($driverExportRoot, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
$driverName = $driverFolder.Substring($driverExportRoot.Length).TrimStart('\')
|
||||
}
|
||||
|
||||
try {
|
||||
Invoke-WinUtilISODism -Arguments @('/English', "/Image:$mountDir", '/Add-Driver', "/Driver:$driverFolder", '/Recurse') -Operation "add-driver:$driverName" | Out-Null
|
||||
} catch {
|
||||
& $Logger "Warning: failed to add driver package '$driverName': $_"
|
||||
$failedDriverFolder = $driverFolder
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $failedDriverFolder) {
|
||||
& $Logger "Warning: failed to add driver package '$driverName': $_"
|
||||
$failedDriverFolder = $driverFolder
|
||||
break
|
||||
}
|
||||
|
||||
& $Logger "Discarding the potentially partial install.wim mount before continuing without '$driverName'."
|
||||
try {
|
||||
Invoke-WinUtilISODism -Arguments @('/English', '/Unmount-Image', "/MountDir:$mountDir", '/Discard') -Operation 'discard' | Out-Null
|
||||
$imageMounted = $false
|
||||
} catch {
|
||||
throw "Failed to discard the potentially partial install.wim mount after driver package '$driverName' failed: $_"
|
||||
}
|
||||
|
||||
$remainingDriverFolders = @($remainingDriverFolders | Where-Object { $_ -ne $failedDriverFolder })
|
||||
}
|
||||
|
||||
$addedCount = $remainingDriverFolders.Count
|
||||
if ($addedCount -eq 0) {
|
||||
# Boot-storage drivers staged for WinPE remain available to Windows Setup.
|
||||
& $Logger "Warning: none of the $($rootPackageFolders.Count) exported driver packages could be added; continuing with an unmodified install.wim."
|
||||
} else {
|
||||
& $Logger "Added $addedCount of $($rootPackageFolders.Count) driver packages to install.wim."
|
||||
& $Logger 'Committing the driver-only install.wim change...'
|
||||
Invoke-WinUtilISODism -Arguments @('/English', '/Unmount-Image', "/MountDir:$mountDir", '/Commit') -Operation 'commit' | Out-Null
|
||||
if (-not $failedDriverFolder) {
|
||||
break
|
||||
}
|
||||
|
||||
& $Logger "Discarding the potentially partial install.wim mount before continuing without '$driverName'."
|
||||
try {
|
||||
Invoke-WinUtilISODism -Arguments @('/English', '/Unmount-Image', "/MountDir:$mountDir", '/Discard') -Operation 'discard' | Out-Null
|
||||
$imageMounted = $false
|
||||
|
||||
$metadataAfter = Get-WinUtilISOWimMetadata -ImagePath $InstallImagePath -Index $InstallImageIndex
|
||||
Assert-WinUtilISOWimMetadata -Before $metadataBefore -After $metadataAfter
|
||||
& $Logger 'Driver injection complete; install.wim metadata validation passed.'
|
||||
$DriversInjected.Value = $true
|
||||
} catch {
|
||||
throw "Failed to discard the potentially partial install.wim mount after driver package '$driverName' failed: $_"
|
||||
}
|
||||
|
||||
$remainingDriverFolders = @($remainingDriverFolders | Where-Object { $_ -ne $failedDriverFolder })
|
||||
}
|
||||
|
||||
$addedCount = $remainingDriverFolders.Count
|
||||
if ($addedCount -eq 0) {
|
||||
# Boot-storage drivers staged for WinPE remain available to Windows Setup.
|
||||
& $Logger "Warning: none of the $($rootPackageFolders.Count) exported driver packages could be added; continuing with an unmodified install.wim."
|
||||
} else {
|
||||
& $Logger "Added $addedCount of $($rootPackageFolders.Count) driver packages to install.wim."
|
||||
& $Logger 'Committing the driver-only install.wim change...'
|
||||
Invoke-WinUtilISODism -Arguments @('/English', '/Unmount-Image', "/MountDir:$mountDir", '/Commit') -Operation 'commit' | Out-Null
|
||||
$imageMounted = $false
|
||||
|
||||
$metadataAfter = Get-WinUtilISOWimMetadata -ImagePath $InstallImagePath -Index $InstallImageIndex
|
||||
Assert-WinUtilISOWimMetadata -Before $metadataBefore -After $metadataAfter
|
||||
& $Logger 'Driver injection complete; install.wim metadata validation passed.'
|
||||
$DriversInjected.Value = $true
|
||||
}
|
||||
} finally {
|
||||
if ($imageMounted -or (Test-WinUtilISOMountedImage -Path $mountDir)) {
|
||||
|
||||
@@ -473,11 +473,11 @@ Describe "Win11 Creator setup media" {
|
||||
Test-Path (Join-Path $winpeDriverRoot 'net_pkg\network.inf') | Should -BeFalse
|
||||
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Mount-Image' }).Count | Should -Be 1
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Add-Driver' }).Count | Should -Be $script:expectedRootPackages
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Add-Driver' }).Count | Should -Be 9
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Unmount-Image\|.*\|/Commit' }).Count | Should -Be 1
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Get-WimInfo' }).Count | Should -Be 2
|
||||
($script:dismCalls -join "`n") | Should -Not -Match '/Cleanup-Image|/Export-Image'
|
||||
($logs -join '|') | Should -Match "Added $script:expectedRootPackages of $script:expectedRootPackages driver packages"
|
||||
($logs -join '|') | Should -Match "Added 9 of 9 driver packages"
|
||||
|
||||
# nested_pkg holds INFs at its root and under x64. The root add already recurses
|
||||
# into x64, so the subfolder must not get an /Add-Driver call of its own.
|
||||
@@ -488,14 +488,13 @@ Describe "Win11 Creator setup media" {
|
||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($answerFile.NameTable)
|
||||
$nsMgr.AddNamespace('sg', 'https://schneegans.de/windows/unattend-generator/')
|
||||
$answerFile.SelectSingleNode('//sg:File[@path="C:\Windows\Setup\Scripts\WinUtil-InstallDrivers.ps1"]', $nsMgr) | Should -BeNullOrEmpty
|
||||
($logs -join '|') | Should -Match 'Exported 9 of 11 driver packages \(2 staged for WinPE, 2 excluded\)'
|
||||
($logs -join '|') | Should -Match "Excluding extension-class driver package '.*hdx_asusext_apot_g5-tse.*'"
|
||||
($logs -join '|') | Should -Match 'Exported 10 of 11 driver packages \(2 staged for WinPE, 1 excluded\)'
|
||||
($logs -join '|') | Should -Match "Excluding stale duplicate driver package '.*ntprint\.inf_x86_7426e1b60aa62272' \(DriverVer 1/1/2023,10\.0\.26100\.8875\) superseded by '.*ntprint\.inf_x86_58e7118cdecb935e' \(DriverVer 6/1/2024,10\.0\.26100\.9168\)"
|
||||
($logs -join '|') | Should -Match 'install.wim metadata validation passed'
|
||||
($logs -join '|') | Should -Match 'DISM mount completed.'
|
||||
($logs -join '|') | Should -Not -Match '100.0%'
|
||||
|
||||
$script:exportRootAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'hdx_asusext_apot_g5-tse.inf_amd64_aabbccddeeff0011')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'hdx_asusext_apot_g5-tse.inf_amd64_aabbccddeeff0011')
|
||||
$script:exportRootAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'ntprint.inf_x86_7426e1b60aa62272')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'ntprint.inf_x86_58e7118cdecb935e')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'system_pkg')
|
||||
@@ -506,8 +505,8 @@ Describe "Win11 Creator setup media" {
|
||||
}
|
||||
}
|
||||
|
||||
It "excludes Class=Extension driver packages from Add-Driver regardless of vendor or case" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoExtensionExclude_$([guid]::NewGuid())"
|
||||
It "injects Class=Extension driver packages like any other export" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoExtensionInject_$([guid]::NewGuid())"
|
||||
$installWim = Join-Path $contentRoot 'sources\install.wim'
|
||||
$template = Get-Content -Path $script:autoUnattendPath -Raw
|
||||
$logs = [System.Collections.Generic.List[string]]::new()
|
||||
@@ -528,15 +527,12 @@ Describe "Win11 Creator setup media" {
|
||||
$logs.Add([string]$message)
|
||||
}
|
||||
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Add-Driver' }).Count | Should -Be 1
|
||||
($logs -join '|') | Should -Match 'Exported 1 of 3 driver packages \(0 staged for WinPE, 2 excluded\)'
|
||||
($logs -join '|') | Should -Match "Excluding extension-class driver package '.*ext_pkg_lower'"
|
||||
($logs -join '|') | Should -Match "Excluding extension-class driver package '.*ext_pkg_quoted'"
|
||||
($logs -join '|') | Should -Not -Match "Excluding extension-class driver package '.*net_pkg'"
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Add-Driver' }).Count | Should -Be 3
|
||||
($logs -join '|') | Should -Match 'Exported 3 of 3 driver packages \(0 staged for WinPE, 0 excluded\)'
|
||||
$driversInjected.Value | Should -BeTrue
|
||||
|
||||
$script:exportRootAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'ext_pkg_lower')
|
||||
$script:exportRootAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'ext_pkg_quoted')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'ext_pkg_lower')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'ext_pkg_quoted')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'net_pkg')
|
||||
} finally {
|
||||
Remove-Item Function:\dism.exe -ErrorAction SilentlyContinue
|
||||
@@ -544,15 +540,16 @@ Describe "Win11 Creator setup media" {
|
||||
}
|
||||
}
|
||||
|
||||
It "preserves a retained nested package when its parent package is excluded" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoNestedRetained_$([guid]::NewGuid())"
|
||||
It "keeps a stale duplicate folder that contains a retained nested package" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoStaleNestedRetained_$([guid]::NewGuid())"
|
||||
$installWim = Join-Path $contentRoot 'sources\install.wim'
|
||||
$template = Get-Content -Path $script:autoUnattendPath -Raw
|
||||
$logs = [System.Collections.Generic.List[string]]::new()
|
||||
|
||||
New-WinUtilDriverExportHarness -Fixtures @(
|
||||
@{ Path = 'parent_pkg'; Name = 'extension.inf'; Class = 'Extension' },
|
||||
@{ Path = 'parent_pkg\retained_child'; Name = 'network.inf'; Class = 'Net' }
|
||||
@{ Path = 'main.inf_amd64_11111111aaaaaaaa'; Name = 'main.inf'; Class = 'Net'; DriverVer = '1/1/2023,1.0.0.0' },
|
||||
@{ Path = 'main.inf_amd64_22222222bbbbbbbb'; Name = 'main.inf'; Class = 'Net'; DriverVer = '6/1/2024,2.0.0.0' },
|
||||
@{ Path = 'main.inf_amd64_11111111aaaaaaaa\retained_child'; Name = 'network.inf'; Class = 'Net' }
|
||||
)
|
||||
|
||||
try {
|
||||
@@ -565,14 +562,12 @@ Describe "Win11 Creator setup media" {
|
||||
$logs.Add([string]$message)
|
||||
}
|
||||
|
||||
$addDriverCalls = @($script:dismCalls | Where-Object { $_ -match '/Add-Driver' })
|
||||
$addDriverCalls.Count | Should -Be 1
|
||||
$addDriverCalls[0] | Should -Match ([regex]::Escape('parent_pkg\retained_child'))
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'parent_pkg')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'parent_pkg\retained_child')
|
||||
$script:exportedInfsAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'parent_pkg\extension.inf')
|
||||
$script:exportedInfsAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'parent_pkg\retained_child\network.inf')
|
||||
($logs -join '|') | Should -Match "Keeping excluded driver package directory '.*parent_pkg' because it contains a retained nested package"
|
||||
($logs -join '|') | Should -Match "Excluding stale duplicate driver package '.*main\.inf_amd64_11111111aaaaaaaa' \(DriverVer 1/1/2023,1\.0\.0\.0\) superseded by '.*main\.inf_amd64_22222222bbbbbbbb' \(DriverVer 6/1/2024,2\.0\.0\.0\)"
|
||||
($logs -join '|') | Should -Match "Keeping excluded driver package directory '.*main\.inf_amd64_11111111aaaaaaaa' because it contains a retained nested package"
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Add-Driver' }).Count | Should -Be 2
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'main.inf_amd64_11111111aaaaaaaa')
|
||||
$script:exportedInfsAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'main.inf_amd64_11111111aaaaaaaa\main.inf')
|
||||
$script:exportedInfsAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'main.inf_amd64_11111111aaaaaaaa\retained_child\network.inf')
|
||||
$driversInjected.Value | Should -BeTrue
|
||||
} finally {
|
||||
Remove-Item Function:\dism.exe -ErrorAction SilentlyContinue
|
||||
@@ -580,15 +575,16 @@ Describe "Win11 Creator setup media" {
|
||||
}
|
||||
}
|
||||
|
||||
It "removes an excluded nested INF before recursively adding its retained ancestor" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoNestedExcluded_$([guid]::NewGuid())"
|
||||
It "removes a stale duplicate INF before recursively adding its retained ancestor" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoStaleNestedExcluded_$([guid]::NewGuid())"
|
||||
$installWim = Join-Path $contentRoot 'sources\install.wim'
|
||||
$template = Get-Content -Path $script:autoUnattendPath -Raw
|
||||
|
||||
New-WinUtilDriverExportHarness -Fixtures @(
|
||||
@{ Path = 'root_pkg'; Name = 'root.inf'; Class = 'Net' },
|
||||
@{ Path = 'root_pkg\excluded_child'; Name = 'extension.inf'; Class = 'Extension' },
|
||||
@{ Path = 'root_pkg\excluded_child\retained_grandchild'; Name = 'storage.inf'; Class = 'SCSIAdapter' }
|
||||
@{ Path = 'root_pkg\dup.inf_amd64_11111111aaaaaaaa'; Name = 'dup.inf'; Class = 'Media'; DriverVer = '1/1/2020,1.0.0.0' },
|
||||
@{ Path = 'root_pkg\dup.inf_amd64_22222222bbbbbbbb'; Name = 'dup.inf'; Class = 'Media'; DriverVer = '6/1/2024,2.0.0.0' },
|
||||
@{ Path = 'root_pkg\dup.inf_amd64_11111111aaaaaaaa\retained_grandchild'; Name = 'storage.inf'; Class = 'SCSIAdapter' }
|
||||
)
|
||||
|
||||
try {
|
||||
@@ -600,43 +596,11 @@ Describe "Win11 Creator setup media" {
|
||||
$addDriverCalls = @($script:dismCalls | Where-Object { $_ -match '/Add-Driver' })
|
||||
$addDriverCalls.Count | Should -Be 1
|
||||
$addDriverCalls[0] | Should -Match ([regex]::Escape('/Driver:' + (Join-Path $script:driverExportRoot 'root_pkg')))
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\excluded_child')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\excluded_child\retained_grandchild')
|
||||
$script:exportRootAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\dup.inf_amd64_11111111aaaaaaaa')
|
||||
$script:exportedInfsAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\root.inf')
|
||||
$script:exportedInfsAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'root_pkg\excluded_child\extension.inf')
|
||||
$script:exportedInfsAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\excluded_child\retained_grandchild\storage.inf')
|
||||
} finally {
|
||||
Remove-Item Function:\dism.exe -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path $contentRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
It "validates WIM metadata and reports no injection when every package is excluded" {
|
||||
$contentRoot = Join-Path ([IO.Path]::GetTempPath()) "WinUtilIsoAllExcluded_$([guid]::NewGuid())"
|
||||
$installWim = Join-Path $contentRoot 'sources\install.wim'
|
||||
$template = Get-Content -Path $script:autoUnattendPath -Raw
|
||||
$logs = [System.Collections.Generic.List[string]]::new()
|
||||
|
||||
New-WinUtilDriverExportHarness -Fixtures @(
|
||||
@{ Path = 'ext_pkg_a'; Name = 'a.inf'; Class = 'Extension' },
|
||||
@{ Path = 'ext_pkg_b'; Name = 'b.inf'; Class = 'Extension' }
|
||||
)
|
||||
|
||||
try {
|
||||
New-Item -Path (Split-Path $installWim -Parent) -ItemType Directory -Force | Out-Null
|
||||
Set-Content -Path $installWim -Value 'mock-wim'
|
||||
. $script:isoScriptPath
|
||||
$driversInjected = [ref]$true
|
||||
Invoke-WinUtilISOScript -ISOContentsDir $contentRoot -AutoUnattendXml $template -InjectCurrentSystemDrivers $true -InstallImagePath $installWim -InstallImageIndex 6 -InstallEditionId 'Professional' -DriversInjected $driversInjected -Log {
|
||||
param($message)
|
||||
$logs.Add([string]$message)
|
||||
}
|
||||
|
||||
$driversInjected.Value | Should -BeFalse
|
||||
($logs -join '|') | Should -Match 'No drivers found to inject: every exported package was excluded'
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Get-WimInfo' }).Count | Should -Be 1
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Mount-Image' }).Count | Should -Be 0
|
||||
@($script:dismCalls | Where-Object { $_ -match '/Add-Driver' }).Count | Should -Be 0
|
||||
$script:exportedInfsAtAddDriver | Should -Not -Contain (Join-Path $script:driverExportRoot 'root_pkg\dup.inf_amd64_11111111aaaaaaaa\dup.inf')
|
||||
$script:exportedInfsAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\dup.inf_amd64_11111111aaaaaaaa\retained_grandchild\storage.inf')
|
||||
$script:exportedInfsAtAddDriver | Should -Contain (Join-Path $script:driverExportRoot 'root_pkg\dup.inf_amd64_22222222bbbbbbbb\dup.inf')
|
||||
} finally {
|
||||
Remove-Item Function:\dism.exe -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path $contentRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Reference in New Issue
Block a user