mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
Refactor Win32 app installation to process sources separately
Updates the Win32 app installation script to handle WinGet-sourced apps and user-defined apps in two separate batches instead of merging them. This ensures all WinGet apps are installed before any user-defined apps. The core installation logic is extracted into a reusable function, improving script structure and readability. Additionally, removes a pause command and a redundant console message from other scripts to improve automation flow.
This commit is contained in:
@@ -266,5 +266,4 @@ foreach ($appFolder in Get-ChildItem -Path $basePath -Directory) {
|
|||||||
|
|
||||||
# Final cleanup
|
# Final cleanup
|
||||||
Write-Host "Installation process finished."
|
Write-Host "Installation process finished."
|
||||||
pause
|
|
||||||
Remove-TemporaryFiles
|
Remove-TemporaryFiles
|
||||||
@@ -63,24 +63,85 @@ function Invoke-Process {
|
|||||||
return $cmd
|
return $cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Install-Applications {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[array]$apps
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($apps.Count -eq 0) {
|
||||||
|
Write-Host "No applications to install from this source."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Total apps to install from this source: $($apps.Count)"
|
||||||
|
|
||||||
|
# Sort all apps by priority
|
||||||
|
$sortedApps = $apps | Sort-Object -Property Priority
|
||||||
|
|
||||||
|
# Install each app
|
||||||
|
foreach ($app in $sortedApps) {
|
||||||
|
# Check if required properties exist
|
||||||
|
if (-not $app.PSObject.Properties['Name'] -or -not $app.PSObject.Properties['CommandLine'] -or -not $app.PSObject.Properties['Arguments']) {
|
||||||
|
Write-Warning "Skipping app due to missing required properties (Name, CommandLine, Arguments): $($app | ConvertTo-Json -Depth 1 -Compress)"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Installing $($app.Name)..."
|
||||||
|
|
||||||
|
# Wait until no MSIExec installation is running
|
||||||
|
while ($true) {
|
||||||
|
try {
|
||||||
|
# Try to open the MSIExec global mutex
|
||||||
|
$Mutex = [System.Threading.Mutex]::OpenExisting("Global\_MSIExecute")
|
||||||
|
# Dispose releases the handle from our script only.
|
||||||
|
$Mutex.Dispose()
|
||||||
|
Write-Host "Another MSIExec installer is running. Waiting for 5 seconds before rechecking..."
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
}
|
||||||
|
catch [System.Threading.WaitHandleCannotBeOpenedException] {
|
||||||
|
# If we can't open the mutex, it means no MSIExec installation is running
|
||||||
|
break
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
# Handle other potential errors when checking the mutex
|
||||||
|
Write-Warning "Error checking MSIExec mutex: $_. Proceeding with caution."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Construct the argument list properly, handling potential array vs string
|
||||||
|
$argumentsToPass = if ($app.Arguments -is [array]) { $app.Arguments } else { @($app.Arguments) }
|
||||||
|
|
||||||
|
Write-Host "Running command: $($app.CommandLine) $($argumentsToPass -join ' ')"
|
||||||
|
$result = Invoke-Process -FilePath $($app.CommandLine) -ArgumentList $argumentsToPass
|
||||||
|
Write-Host "$($app.Name) exited with exit code: $($result.ExitCode)`r`n"
|
||||||
|
} catch {
|
||||||
|
Write-Error "Error occurred while installing $($app.Name): $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Define paths for the JSON files
|
# Define paths for the JSON files
|
||||||
$wingetAppsJsonFile = "$PSScriptRoot\WinGetWin32Apps.json"
|
$wingetAppsJsonFile = "$PSScriptRoot\WinGetWin32Apps.json"
|
||||||
# Look for UserAppList.json one directory level up from the script's location. This keeps the user specific json files (AppList.json and UserAppList.json in the Apps dir)
|
# Look for UserAppList.json one directory level up from the script's location. This keeps the user specific json files (AppList.json and UserAppList.json in the Apps dir)
|
||||||
$userAppsJsonFile = Join-Path -Path (Split-Path -Parent $PSScriptRoot) -ChildPath "UserAppList.json"
|
$userAppsJsonFile = Join-Path -Path (Split-Path -Parent $PSScriptRoot) -ChildPath "UserAppList.json"
|
||||||
|
|
||||||
# Initialize an empty array to hold all apps
|
# Initialize empty arrays for apps from each source
|
||||||
$allApps = @()
|
$wingetApps = @()
|
||||||
|
$userApps = @()
|
||||||
|
|
||||||
# Read the WinGetWin32Apps.json file if it exists
|
# Read the WinGetWin32Apps.json file if it exists
|
||||||
if (Test-Path -Path $wingetAppsJsonFile) {
|
if (Test-Path -Path $wingetAppsJsonFile) {
|
||||||
Write-Host "Processing WinGetWin32Apps.json first..."
|
Write-Host "Processing WinGetWin32Apps.json..."
|
||||||
try {
|
try {
|
||||||
$wingetApps = Get-Content -Path $wingetAppsJsonFile -Raw -ErrorAction Stop | ConvertFrom-Json
|
$wingetContent = Get-Content -Path $wingetAppsJsonFile -Raw -ErrorAction Stop | ConvertFrom-Json
|
||||||
if ($wingetApps -is [array]) {
|
if ($wingetContent -is [array]) {
|
||||||
$allApps += $wingetApps
|
$wingetApps = $wingetContent
|
||||||
Write-Host "Found $(($wingetApps | Measure-Object).Count) WinGet Win32 apps."
|
Write-Host "Found $(($wingetApps | Measure-Object).Count) WinGet Win32 apps."
|
||||||
} elseif ($wingetApps) {
|
} elseif ($wingetContent) {
|
||||||
$allApps += @($wingetApps) # Ensure it's added as an array element
|
$wingetApps = @($wingetContent) # Ensure it's an array
|
||||||
Write-Host "Found 1 WinGet Win32 app."
|
Write-Host "Found 1 WinGet Win32 app."
|
||||||
} else {
|
} else {
|
||||||
Write-Host "WinGetWin32Apps.json is empty or invalid."
|
Write-Host "WinGetWin32Apps.json is empty or invalid."
|
||||||
@@ -92,16 +153,21 @@ if (Test-Path -Path $wingetAppsJsonFile) {
|
|||||||
Write-Host "WinGetWin32Apps.json file not found. Skipping."
|
Write-Host "WinGetWin32Apps.json file not found. Skipping."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Install WinGet apps if any were found
|
||||||
|
if ($wingetApps.Count -gt 0) {
|
||||||
|
Install-Applications -apps $wingetApps
|
||||||
|
}
|
||||||
|
|
||||||
# Read the UserAppList.json file if it exists
|
# Read the UserAppList.json file if it exists
|
||||||
if (Test-Path -Path $userAppsJsonFile) {
|
if (Test-Path -Path $userAppsJsonFile) {
|
||||||
Write-Host "Processing UserAppList.json next..."
|
Write-Host "Processing UserAppList.json..."
|
||||||
try {
|
try {
|
||||||
$userApps = Get-Content -Path $userAppsJsonFile -Raw -ErrorAction Stop | ConvertFrom-Json
|
$userContent = Get-Content -Path $userAppsJsonFile -Raw -ErrorAction Stop | ConvertFrom-Json
|
||||||
if ($userApps -is [array]) {
|
if ($userContent -is [array]) {
|
||||||
$allApps += $userApps
|
$userApps = $userContent
|
||||||
Write-Host "Found $(($userApps | Measure-Object).Count) user-defined apps."
|
Write-Host "Found $(($userApps | Measure-Object).Count) user-defined apps."
|
||||||
} elseif ($userApps) {
|
} elseif ($userContent) {
|
||||||
$allApps += @($userApps) # Ensure it's added as an array element
|
$userApps = @($userContent) # Ensure it's an array
|
||||||
Write-Host "Found 1 user-defined app."
|
Write-Host "Found 1 user-defined app."
|
||||||
} else {
|
} else {
|
||||||
Write-Host "UserAppList.json is empty or invalid."
|
Write-Host "UserAppList.json is empty or invalid."
|
||||||
@@ -113,58 +179,15 @@ if (Test-Path -Path $userAppsJsonFile) {
|
|||||||
Write-Host "UserAppList.json file not found. Skipping."
|
Write-Host "UserAppList.json file not found. Skipping."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if there are any apps to install
|
# Install User apps if any were found
|
||||||
if ($allApps.Count -eq 0) {
|
if ($userApps.Count -gt 0) {
|
||||||
|
Install-Applications -apps $userApps
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if any apps were installed at all
|
||||||
|
if ($wingetApps.Count -eq 0 -and $userApps.Count -eq 0) {
|
||||||
Write-Host "No Win32 apps found in either WinGetWin32Apps.json or UserAppList.json. Exiting."
|
Write-Host "No Win32 apps found in either WinGetWin32Apps.json or UserAppList.json. Exiting."
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Total apps to install: $($allApps.Count)"
|
|
||||||
|
|
||||||
# Sort all apps by priority
|
|
||||||
$sortedApps = $allApps | Sort-Object -Property Priority
|
|
||||||
|
|
||||||
# Install each app
|
|
||||||
foreach ($app in $sortedApps) {
|
|
||||||
# Check if required properties exist
|
|
||||||
if (-not $app.PSObject.Properties['Name'] -or -not $app.PSObject.Properties['CommandLine'] -or -not $app.PSObject.Properties['Arguments']) {
|
|
||||||
Write-Warning "Skipping app due to missing required properties (Name, CommandLine, Arguments): $($app | ConvertTo-Json -Depth 1 -Compress)"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Installing $($app.Name)..."
|
|
||||||
|
|
||||||
# Wait until no MSIExec installation is running
|
|
||||||
while ($true) {
|
|
||||||
try {
|
|
||||||
# Try to open the MSIExec global mutex
|
|
||||||
$Mutex = [System.Threading.Mutex]::OpenExisting("Global\_MSIExecute")
|
|
||||||
# Dispose releases the handle from our script only.
|
|
||||||
$Mutex.Dispose()
|
|
||||||
Write-Host "Another MSIExec installer is running. Waiting for 5 seconds before rechecking..."
|
|
||||||
Start-Sleep -Seconds 5
|
|
||||||
}
|
|
||||||
catch [System.Threading.WaitHandleCannotBeOpenedException] {
|
|
||||||
# If we can't open the mutex, it means no MSIExec installation is running
|
|
||||||
break
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
# Handle other potential errors when checking the mutex
|
|
||||||
Write-Warning "Error checking MSIExec mutex: $_. Proceeding with caution."
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
# Construct the argument list properly, handling potential array vs string
|
|
||||||
$argumentsToPass = if ($app.Arguments -is [array]) { $app.Arguments } else { @($app.Arguments) }
|
|
||||||
|
|
||||||
Write-Host "Running command: $($app.CommandLine) $($argumentsToPass -join ' ')"
|
|
||||||
$result = Invoke-Process -FilePath $($app.CommandLine) -ArgumentList $argumentsToPass
|
|
||||||
Write-Host "$($app.Name) exited with exit code: $($result.ExitCode)`r`n"
|
|
||||||
} catch {
|
|
||||||
Write-Error "Error occurred while installing $($app.Name): $_"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "All Win32 app installations attempted."
|
Write-Host "All Win32 app installations attempted."
|
||||||
@@ -682,7 +682,6 @@ if ($null -eq $DriverSourcePath) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
WriteLog "Drivers folder not found at $DriversPath. Skipping driver installation."
|
WriteLog "Drivers folder not found at $DriversPath. Skipping driver installation."
|
||||||
Write-Host "Drivers folder not found at $DriversPath. Skipping driver installation."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#Partition drive
|
#Partition drive
|
||||||
|
|||||||
Reference in New Issue
Block a user