mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
Refactor WinGet app handling and add command overrides
Improves the reliability of WinGet app processing by making several key changes. The build process now deletes the `WinGetWin32Apps.json` file before each run to ensure it is always freshly generated. The UI no longer relies on `WinGetWin32Apps.json` to detect previously downloaded content. Instead, it checks directly for the application's content on disk, preventing unnecessary re-downloads. This change also introduces a feature allowing users to override the default silent install commands for Win32 apps. By specifying `CommandLine` or `Arguments` properties in `AppList.json`, these values will be used to update the corresponding entries in `WinGetWin32Apps.json` during the build process.
This commit is contained in:
@@ -5871,6 +5871,13 @@ if ($AllowVHDXCaching) {
|
||||
throw $_
|
||||
}
|
||||
}
|
||||
|
||||
# Remove WinGetWin32Apps.json so it is always rebuilt next run
|
||||
if (Test-Path -Path $wingetWin32jsonFile -PathType Leaf) {
|
||||
WriteLog "Removing $wingetWin32jsonFile"
|
||||
Remove-Item -Path $wingetWin32jsonFile -Force -ErrorAction SilentlyContinue
|
||||
WriteLog "Removal complete"
|
||||
}
|
||||
#Set $LongPathsEnabled registry value back to original value. $LongPathsEnabled could be $null if the registry value was not found
|
||||
if ($null -eq $LongPathsEnabled) {
|
||||
Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -ErrorAction SilentlyContinue
|
||||
|
||||
@@ -22,7 +22,8 @@ function Get-Application {
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WindowsArch,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$OrchestrationPath
|
||||
[string]$OrchestrationPath,
|
||||
[switch]$SkipWin32Json
|
||||
)
|
||||
|
||||
# Block Company Portal from winget source
|
||||
@@ -48,6 +49,29 @@ function Get-Application {
|
||||
# Check if the folder is not empty.
|
||||
if (Get-ChildItem -Path $appBaseFolderPathForCheck -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1) {
|
||||
WriteLog "Application '$AppName' appears to be already downloaded as content exists in '$appBaseFolderPathForCheck'. Skipping download."
|
||||
|
||||
# Add silent install command(s) only if not skipping JSON generation (build-time scenario)
|
||||
$appIsWin32Existing = ($Source -eq 'winget' -or ($Source -eq 'msstore' -and $AppId.StartsWith('XP')))
|
||||
if ($appIsWin32Existing -and -not $SkipWin32Json) {
|
||||
$win32BasePath = Join-Path -Path "$AppsPath\Win32" -ChildPath $AppName
|
||||
if (Test-Path -Path $win32BasePath -PathType Container) {
|
||||
$archFolders = Get-ChildItem -Path $win32BasePath -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -in @('x86', 'x64', 'arm64') }
|
||||
if ($archFolders) {
|
||||
foreach ($archFolder in $archFolders) {
|
||||
WriteLog "Adding silent install command for pre-downloaded $AppName ($($archFolder.Name)) to $OrchestrationPath\WinGetWin32Apps.json"
|
||||
Add-Win32SilentInstallCommand -AppFolder $AppName -AppFolderPath $archFolder.FullName -OrchestrationPath $OrchestrationPath -SubFolder $archFolder.Name | Out-Null
|
||||
}
|
||||
}
|
||||
else {
|
||||
WriteLog "Adding silent install command for pre-downloaded $AppName to $OrchestrationPath\WinGetWin32Apps.json"
|
||||
Add-Win32SilentInstallCommand -AppFolder $AppName -AppFolderPath $win32BasePath -OrchestrationPath $OrchestrationPath | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($appIsWin32Existing -and $SkipWin32Json) {
|
||||
WriteLog "Skipping WinGetWin32Apps.json regeneration for pre-downloaded $AppName (UI mode)."
|
||||
}
|
||||
|
||||
return 0 # Success, already present
|
||||
}
|
||||
}
|
||||
@@ -196,8 +220,14 @@ function Get-Application {
|
||||
}
|
||||
# If app is in Win32 folder, add the silent install command to the WinGetWin32Apps.json file
|
||||
elseif ($appFolderPath -match 'Win32') {
|
||||
WriteLog "$AppName is a Win32 app. Adding silent install command to $OrchestrationPath\WinGetWin32Apps.json"
|
||||
$result = Add-Win32SilentInstallCommand -AppFolder $AppName -AppFolderPath $appFolderPath -OrchestrationPath $OrchestrationPath -SubFolder $subFolderForCommand
|
||||
if (-not $SkipWin32Json) {
|
||||
WriteLog "$AppName is a Win32 app. Adding silent install command to $OrchestrationPath\WinGetWin32Apps.json"
|
||||
$result = Add-Win32SilentInstallCommand -AppFolder $AppName -AppFolderPath $appFolderPath -OrchestrationPath $OrchestrationPath -SubFolder $subFolderForCommand
|
||||
}
|
||||
else {
|
||||
WriteLog "$AppName is a Win32 app. Skipping WinGetWin32Apps.json generation (UI mode)."
|
||||
$result = 0
|
||||
}
|
||||
}
|
||||
else {
|
||||
# For any other case, set result to 0 (success)
|
||||
@@ -314,7 +344,7 @@ function Get-Apps {
|
||||
if (-not (Test-Path -Path $storeAppsFolder -PathType Container)) {
|
||||
New-Item -Path $storeAppsFolder -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
|
||||
foreach ($storeApp in $StoreApps) {
|
||||
try {
|
||||
$appArch = if ($storeApp.PSObject.Properties['architecture']) { $storeApp.architecture } else { $WindowsArch }
|
||||
@@ -326,6 +356,62 @@ function Get-Apps {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Post-processing: Override CommandLine / Arguments from AppList.json if provided
|
||||
# Users may supply custom silent install commands or arguments. These optional
|
||||
# properties (CommandLine, Arguments) in AppList.json replace the auto-generated
|
||||
# values in WinGetWin32Apps.json. Keyed by Name.
|
||||
try {
|
||||
$overrideMap = @{}
|
||||
foreach ($app in $apps.apps) {
|
||||
if ($app.source -in @('winget', 'msstore')) {
|
||||
$hasCmd = ($app.PSObject.Properties['CommandLine'] -and -not [string]::IsNullOrWhiteSpace($app.CommandLine))
|
||||
$hasArgs = ($app.PSObject.Properties['Arguments'] -and -not [string]::IsNullOrWhiteSpace($app.Arguments))
|
||||
if ($hasCmd -or $hasArgs) {
|
||||
$overrideMap[$app.name] = @{
|
||||
CommandLine = if ($hasCmd) { $app.CommandLine } else { $null }
|
||||
Arguments = if ($hasArgs) { $app.Arguments } else { $null }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($overrideMap.Count -gt 0) {
|
||||
$winGetWin32Path = Join-Path -Path $OrchestrationPath -ChildPath 'WinGetWin32Apps.json'
|
||||
if (Test-Path -Path $winGetWin32Path) {
|
||||
[array]$appsDataUpdated = Get-Content -Path $winGetWin32Path -Raw | ConvertFrom-Json
|
||||
$changed = $false
|
||||
foreach ($entry in $appsDataUpdated) {
|
||||
if ($overrideMap.ContainsKey($entry.Name)) {
|
||||
$ov = $overrideMap[$entry.Name]
|
||||
if ($ov.CommandLine) {
|
||||
WriteLog "Override (AppList.json) CommandLine for $($entry.Name)"
|
||||
$entry.CommandLine = $ov.CommandLine
|
||||
$changed = $true
|
||||
}
|
||||
if ($ov.Arguments) {
|
||||
WriteLog "Override (AppList.json) Arguments for $($entry.Name)"
|
||||
$entry.Arguments = $ov.Arguments
|
||||
$changed = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($changed) {
|
||||
$appsDataUpdated | ConvertTo-Json -Depth 10 | Set-Content -Path $winGetWin32Path
|
||||
WriteLog "Applied AppList.json command overrides to WinGetWin32Apps.json"
|
||||
}
|
||||
else {
|
||||
WriteLog "No matching apps required command overrides."
|
||||
}
|
||||
}
|
||||
else {
|
||||
WriteLog "WinGetWin32Apps.json not found; no overrides applied."
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
WriteLog "Failed to apply AppList.json command overrides: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
function Install-WinGet {
|
||||
param (
|
||||
|
||||
@@ -450,70 +450,35 @@ function Start-WingetAppDownloadTask {
|
||||
}
|
||||
}
|
||||
|
||||
# 2. Check previous Winget download
|
||||
if (-not $appFound) {
|
||||
if (-not $appFound) {
|
||||
$wingetWin32jsonFile = Join-Path -Path $OrchestrationPath -ChildPath "WinGetWin32Apps.json"
|
||||
if (Test-Path -Path $wingetWin32jsonFile) {
|
||||
try {
|
||||
$wingetAppsJson = Get-Content -Path $wingetWin32jsonFile -Raw | ConvertFrom-Json
|
||||
# Check if app already exists in WinGetWin32Apps.json
|
||||
# For multi-arch apps, there might be entries like "AppName (x86)" and "AppName (x64)"
|
||||
$existingWin32Entries = @($wingetAppsJson | Where-Object {
|
||||
$_.Name -eq $appName -or
|
||||
$_.Name -eq "$appName (x86)" -or
|
||||
$_.Name -eq "$appName (x64)"
|
||||
})
|
||||
|
||||
if ($existingWin32Entries.Count -gt 0) {
|
||||
$appFolder = Join-Path -Path "$AppsPath\Win32" -ChildPath $appName
|
||||
$appContentFound = $false
|
||||
|
||||
# Check if it's a multi-arch app with subfolders
|
||||
if ($ApplicationItemData.Architecture -eq 'x86 x64') {
|
||||
$x86Folder = Join-Path -Path $appFolder -ChildPath "x86"
|
||||
$x64Folder = Join-Path -Path $appFolder -ChildPath "x64"
|
||||
|
||||
if ((Test-Path -Path $x86Folder -PathType Container) -and (Test-Path -Path $x64Folder -PathType Container)) {
|
||||
$x86Size = (Get-ChildItem -Path $x86Folder -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||
$x64Size = (Get-ChildItem -Path $x64Folder -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||
|
||||
if ($x86Size -gt 1MB -and $x64Size -gt 1MB) {
|
||||
$appContentFound = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Single architecture app
|
||||
if (Test-Path -Path $appFolder -PathType Container) {
|
||||
$folderSize = (Get-ChildItem -Path $appFolder -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||
if ($folderSize -gt 1MB) {
|
||||
$appContentFound = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($appContentFound) {
|
||||
$appFound = $true
|
||||
$status = "Not Downloaded: App already in $wingetWin32jsonFile and found in $appFolder"
|
||||
Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $appId -Status $status
|
||||
WriteLog "Found '$appName' in WinGetWin32Apps.json and content exists in '$appFolder'. Skipping download to prevent duplicate entry."
|
||||
return [PSCustomObject]@{ Id = $appId; Status = $status; ResultCode = 0 }
|
||||
}
|
||||
else {
|
||||
# App entry exists in WinGetWin32Apps.json but folder is missing or incomplete
|
||||
$appFound = $true
|
||||
$status = "App in '$wingetWin32jsonFile' but content folder '$appFolder' not found or incomplete. Remove entry from WinGetWin32Apps.json or restore content."
|
||||
Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $appId -Status $status
|
||||
WriteLog $status
|
||||
return [PSCustomObject]@{ Id = $appId; Status = $status; ResultCode = 1 }
|
||||
}
|
||||
# 2. Check existing downloaded Win32 content (folder-based; no WinGetWin32Apps.json dependency)
|
||||
if (-not $appFound -and $source -eq 'winget') {
|
||||
$appFolder = Join-Path -Path "$AppsPath\Win32" -ChildPath $appName
|
||||
if (Test-Path -Path $appFolder -PathType Container) {
|
||||
$contentFound = $false
|
||||
if ($ApplicationItemData.Architecture -eq 'x86 x64') {
|
||||
$x86Folder = Join-Path -Path $appFolder -ChildPath "x86"
|
||||
$x64Folder = Join-Path -Path $appFolder -ChildPath "x64"
|
||||
if ((Test-Path -Path $x86Folder -PathType Container) -and (Test-Path -Path $x64Folder -PathType Container)) {
|
||||
$x86Size = (Get-ChildItem -Path $x86Folder -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||
$x64Size = (Get-ChildItem -Path $x64Folder -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||
if ($x86Size -gt 1MB -and $x64Size -gt 1MB) {
|
||||
$contentFound = $true
|
||||
}
|
||||
}
|
||||
catch {
|
||||
WriteLog "Warning: Could not read or parse '$wingetWin32jsonFile'. Error: $($_.Exception.Message)"
|
||||
}
|
||||
else {
|
||||
$folderSize = (Get-ChildItem -Path $appFolder -Recurse | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
|
||||
if ($folderSize -gt 1MB) {
|
||||
$contentFound = $true
|
||||
}
|
||||
}
|
||||
if ($contentFound) {
|
||||
$appFound = $true
|
||||
$status = "Not Downloaded: Existing content found in $appFolder"
|
||||
Invoke-ProgressUpdate -ProgressQueue $ProgressQueue -Identifier $appId -Status $status
|
||||
WriteLog "Found existing content for '$appName' in '$appFolder'. Skipping download to prevent duplicate entry."
|
||||
return [PSCustomObject]@{ Id = $appId; Status = $status; ResultCode = 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,7 +599,7 @@ function Start-WingetAppDownloadTask {
|
||||
|
||||
try {
|
||||
# Call Get-Application
|
||||
$resultCode = Get-Application -AppName $appName -AppId $appId -Source $source -AppsPath $AppsPath -WindowsArch $ApplicationItemData.Architecture -OrchestrationPath $OrchestrationPath -ErrorAction Stop
|
||||
$resultCode = Get-Application -AppName $appName -AppId $appId -Source $source -AppsPath $AppsPath -WindowsArch $ApplicationItemData.Architecture -OrchestrationPath $OrchestrationPath -SkipWin32Json -ErrorAction Stop
|
||||
|
||||
# Determine status based on result code
|
||||
switch ($resultCode) {
|
||||
|
||||
Reference in New Issue
Block a user