mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
feat: Enhance installer selection logic in Add-Win32SilentInstallCommand function
- Improved detection of installer candidates by reading YAML configuration for NestedInstallerFiles. - Added logic to resolve silent install switches from YAML, prioritizing block-level settings. - Enhanced fallback mechanisms for selecting installers when multiple candidates are found. - Updated command construction to accommodate new installer resolution logic.
This commit is contained in:
@@ -409,42 +409,153 @@ function Add-Win32SilentInstallCommand {
|
|||||||
[string]$SubFolder
|
[string]$SubFolder
|
||||||
)
|
)
|
||||||
$appName = $AppFolder
|
$appName = $AppFolder
|
||||||
$installerPath = Get-ChildItem -Path "$appFolderPath\*" -Include "*.exe", "*.msi" -File -ErrorAction Stop
|
|
||||||
if (-not $installerPath) {
|
# Discover installer candidates (top-level files as before)
|
||||||
|
$installerCandidates = Get-ChildItem -Path "$appFolderPath\*" -Include "*.exe", "*.msi" -File -ErrorAction SilentlyContinue
|
||||||
|
if (-not $installerCandidates) {
|
||||||
WriteLog "No win32 app installers were found. Skipping the inclusion of $AppFolder"
|
WriteLog "No win32 app installers were found. Skipping the inclusion of $AppFolder"
|
||||||
Remove-Item -Path $AppFolderPath -Recurse -Force
|
Remove-Item -Path $AppFolderPath -Recurse -Force
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Read the exported WinGet YAML
|
||||||
$yamlFile = Get-ChildItem -Path "$appFolderPath\*" -Include "*.yaml" -File -ErrorAction Stop
|
$yamlFile = Get-ChildItem -Path "$appFolderPath\*" -Include "*.yaml" -File -ErrorAction Stop
|
||||||
$yamlContent = Get-Content -Path $yamlFile -Raw
|
$yamlText = Get-Content -Path $yamlFile -Raw
|
||||||
$silentInstallSwitch = [regex]::Match($yamlContent, 'Silent:\s*(.+)').Groups[1].Value.Replace("'", "").Trim()
|
|
||||||
|
# Attempt to resolve the correct installer from YAML NestedInstallerFiles within the matching Architecture block
|
||||||
|
$desiredArch = if (-not [string]::IsNullOrEmpty($SubFolder)) { $SubFolder } else { $null }
|
||||||
|
$relativeFromYaml = $null
|
||||||
|
$blockSilent = $null
|
||||||
|
|
||||||
|
$regexOptions = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase
|
||||||
|
$pattern = '-\s+Architecture:\s*(?<arch>\S+)[\s\S]*?NestedInstallerFiles:\s*-\s*RelativeFilePath:\s*(?<path>.+?)\r?\n'
|
||||||
|
$yamlMatches = [regex]::Matches($yamlText, $pattern, $regexOptions)
|
||||||
|
|
||||||
|
$selectedMatch = $null
|
||||||
|
if ($yamlMatches.Count -gt 0) {
|
||||||
|
if ($desiredArch) {
|
||||||
|
foreach ($m in $yamlMatches) {
|
||||||
|
if ($m.Groups['arch'].Value -ieq $desiredArch) {
|
||||||
|
$selectedMatch = $m
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $selectedMatch) {
|
||||||
|
$selectedMatch = $yamlMatches[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
$pathValue = $selectedMatch.Groups['path'].Value.Trim()
|
||||||
|
$pathValue = $pathValue.Trim("'").Trim('"')
|
||||||
|
$relativeFromYaml = $pathValue
|
||||||
|
|
||||||
|
# Extract a Silent switch from within the same installer block if present
|
||||||
|
$startIndex = $selectedMatch.Index
|
||||||
|
$nextIndex = -1
|
||||||
|
for ($i = 0; $i -lt $yamlMatches.Count; $i++) {
|
||||||
|
if ($yamlMatches[$i].Index -gt $startIndex) {
|
||||||
|
$nextIndex = $yamlMatches[$i].Index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($nextIndex -gt -1) {
|
||||||
|
$blockText = $yamlText.Substring($startIndex, $nextIndex - $startIndex)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$blockText = $yamlText.Substring($startIndex)
|
||||||
|
}
|
||||||
|
$blockSilentMatch = [regex]::Match($blockText, 'InstallerSwitches:[\s\S]*?Silent:\s*(.+?)\r?\n', $regexOptions)
|
||||||
|
if ($blockSilentMatch.Success) {
|
||||||
|
$blockSilent = $blockSilentMatch.Groups[1].Value.Trim().Trim("'").Trim('"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Resolve Silent switch (prefer block-level, fallback to first Silent in file)
|
||||||
|
$silentInstallSwitch = $blockSilent
|
||||||
|
if ([string]::IsNullOrEmpty($silentInstallSwitch)) {
|
||||||
|
$globalSilentMatch = [regex]::Match($yamlText, 'Silent:\s*(.+)', $regexOptions)
|
||||||
|
$silentInstallSwitch = $globalSilentMatch.Groups[1].Value.Trim().Trim("'").Trim('"')
|
||||||
|
}
|
||||||
if (-not $silentInstallSwitch) {
|
if (-not $silentInstallSwitch) {
|
||||||
WriteLog "Silent install switch for $appName could not be found. Skipping the inclusion of $appName."
|
WriteLog "Silent install switch for $appName could not be found. Skipping the inclusion of $appName."
|
||||||
Remove-Item -Path $appFolderPath -Recurse -Force
|
Remove-Item -Path $appFolderPath -Recurse -Force
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
$installer = Split-Path -Path $installerPath -Leaf
|
|
||||||
|
# Choose final installer path and extension
|
||||||
|
$resolvedRelativePath = $null
|
||||||
|
$installerExt = $null
|
||||||
|
|
||||||
|
if ($installerCandidates.Count -eq 1 -and -not $relativeFromYaml) {
|
||||||
|
# Single installer – keep current behavior
|
||||||
|
$resolvedRelativePath = $installerCandidates[0].Name
|
||||||
|
$installerExt = $installerCandidates[0].Extension
|
||||||
|
WriteLog "Single installer detected ($resolvedRelativePath). Using current behavior."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($relativeFromYaml) {
|
||||||
|
$normalizedPath = ($relativeFromYaml -replace '/', '\')
|
||||||
|
$resolvedRelativePath = $normalizedPath
|
||||||
|
$installerExt = [System.IO.Path]::GetExtension($normalizedPath)
|
||||||
|
if ([string]::IsNullOrEmpty($installerExt)) {
|
||||||
|
$leafName = [System.IO.Path]::GetFileName($normalizedPath)
|
||||||
|
$matchedCandidate = $installerCandidates | Where-Object { $_.Name -ieq $leafName } | Select-Object -First 1
|
||||||
|
if ($matchedCandidate) {
|
||||||
|
$installerExt = $matchedCandidate.Extension
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WriteLog "Multiple installers found. Selected by YAML NestedInstallerFiles: $resolvedRelativePath"
|
||||||
|
}
|
||||||
|
if (-not $resolvedRelativePath) {
|
||||||
|
# Fallbacks when YAML lacks NestedInstallerFiles or couldn't be matched
|
||||||
|
$msis = $installerCandidates | Where-Object { $_.Extension -ieq ".msi" }
|
||||||
|
if ($msis.Count -eq 1) {
|
||||||
|
$resolvedRelativePath = $msis[0].Name
|
||||||
|
$installerExt = ".msi"
|
||||||
|
WriteLog "Multiple installers found. YAML not used. Falling back to single MSI: $resolvedRelativePath"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$exes = $installerCandidates | Where-Object { $_.Extension -ieq ".exe" }
|
||||||
|
if ($exes.Count -eq 1) {
|
||||||
|
$resolvedRelativePath = $exes[0].Name
|
||||||
|
$installerExt = ".exe"
|
||||||
|
WriteLog "Multiple installers found. YAML not used. Falling back to single EXE: $resolvedRelativePath"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$first = $installerCandidates | Select-Object -First 1
|
||||||
|
$resolvedRelativePath = $first.Name
|
||||||
|
$installerExt = $first.Extension
|
||||||
|
WriteLog "Multiple installers found and ambiguous. Selecting the first candidate: $resolvedRelativePath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$basePath = "D:\win32\$AppFolder"
|
$basePath = "D:\win32\$AppFolder"
|
||||||
if (-not [string]::IsNullOrEmpty($SubFolder)) {
|
if (-not [string]::IsNullOrEmpty($SubFolder)) {
|
||||||
$basePath = "$basePath\$SubFolder"
|
$basePath = "$basePath\$SubFolder"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($installerPath.Extension -eq ".exe") {
|
# Build final command/arguments
|
||||||
$silentInstallCommand = "$basePath\$installer"
|
if ($installerExt -ieq ".exe") {
|
||||||
}
|
$silentInstallCommand = "$basePath\$resolvedRelativePath"
|
||||||
elseif ($installerPath.Extension -eq ".msi") {
|
|
||||||
$silentInstallCommand = "msiexec"
|
|
||||||
$silentInstallSwitch = "/i `"$basePath\$installer`" $silentInstallSwitch"
|
|
||||||
}
|
}
|
||||||
|
elseif ($installerExt -ieq ".msi") {
|
||||||
|
$silentInstallCommand = "msiexec"
|
||||||
|
$silentInstallSwitch = "/i `"$basePath\$resolvedRelativePath`" $silentInstallSwitch"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Default path usage if extension could not be inferred
|
||||||
|
$silentInstallCommand = "$basePath\$resolvedRelativePath"
|
||||||
|
}
|
||||||
|
|
||||||
# Path to the JSON file
|
# Path to the JSON file
|
||||||
$wingetWin32AppsJson = "$OrchestrationPath\WinGetWin32Apps.json"
|
$wingetWin32AppsJson = "$OrchestrationPath\WinGetWin32Apps.json"
|
||||||
|
|
||||||
# Initialize or load existing JSON data
|
# Initialize or load existing JSON data
|
||||||
if (Test-Path -Path $wingetWin32AppsJson) {
|
if (Test-Path -Path $wingetWin32AppsJson) {
|
||||||
[array]$appsData = Get-Content -Path $wingetWin32AppsJson -Raw | ConvertFrom-Json
|
[array]$appsData = Get-Content -Path $wingetWin32AppsJson -Raw | ConvertFrom-Json
|
||||||
|
|
||||||
# Get highest priority value
|
# Get highest priority value
|
||||||
if ($appsData.Count -gt 0) {
|
if ($appsData.Count -gt 0) {
|
||||||
$highestPriority = $appsData.Count + 1
|
$highestPriority = $appsData.Count + 1
|
||||||
@@ -454,7 +565,7 @@ function Add-Win32SilentInstallCommand {
|
|||||||
$appsData = @()
|
$appsData = @()
|
||||||
$highestPriority = 1
|
$highestPriority = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create new app entry
|
# Create new app entry
|
||||||
$newApp = [PSCustomObject]@{
|
$newApp = [PSCustomObject]@{
|
||||||
Priority = $highestPriority
|
Priority = $highestPriority
|
||||||
@@ -462,12 +573,12 @@ function Add-Win32SilentInstallCommand {
|
|||||||
CommandLine = $silentInstallCommand
|
CommandLine = $silentInstallCommand
|
||||||
Arguments = $silentInstallSwitch
|
Arguments = $silentInstallSwitch
|
||||||
}
|
}
|
||||||
|
|
||||||
$appsData += $newApp
|
$appsData += $newApp
|
||||||
$appsData | ConvertTo-Json -Depth 10 | Set-Content -Path $wingetWin32AppsJson
|
$appsData | ConvertTo-Json -Depth 10 | Set-Content -Path $wingetWin32AppsJson
|
||||||
|
|
||||||
WriteLog "Added $($newApp.Name) to WinGetWin32Apps.json with priority $highestPriority"
|
WriteLog "Added $($newApp.Name) to WinGetWin32Apps.json with priority $highestPriority"
|
||||||
|
|
||||||
# Return 0 for success
|
# Return 0 for success
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user