2024-06-10 15:24:12 -05:00
param (
2024-06-25 21:10:16 +02:00
[ switch ] $Debug ,
2024-08-06 23:35:17 +03:00
[ switch ] $Run ,
[ switch ] $SkipPreprocessing
2024-06-10 15:24:12 -05:00
)
2023-03-07 12:28:00 -08:00
$OFS = " `r`n "
$scriptname = "winutil.ps1"
2024-08-06 23:35:17 +03:00
$workingdir = $PSScriptRoot
2024-06-10 15:24:12 -05:00
2024-02-21 16:06:27 -06:00
# Variable to sync between runspaces
$sync = [ Hashtable ]:: Synchronized ( @ {})
2024-08-06 23:35:17 +03:00
$sync . PSScriptRoot = $workingdir
2024-02-21 16:06:27 -06:00
$sync . configs = @ {}
2023-03-07 12:28:00 -08:00
2024-06-29 00:59:38 +03:00
function Update-Progress {
param (
[ Parameter ( Mandatory , position = 0 )]
[ string ] $StatusMessage ,
2024-08-06 23:35:17 +03:00
[ Parameter ( Mandatory , position = 1 )]
[ ValidateRange ( 0 , 100 )]
2024-06-29 00:59:38 +03:00
[ int ] $Percent ,
2024-08-06 23:35:17 +03:00
[ Parameter ( position = 2 )]
[ string ] $Activity = "Compiling"
2024-06-29 00:59:38 +03:00
)
Write-Progress -Activity $Activity -Status $StatusMessage -PercentComplete $Percent
}
2024-06-10 15:24:12 -05:00
$header = @"
2023-03-07 12:28:00 -08:00
################################################################################################################
### ###
### WARNING: This file is automatically generated DO NOT modify this file directly as it will be overwritten ###
### ###
################################################################################################################
2024-06-10 15:24:12 -05:00
"@
2023-03-07 12:28:00 -08:00
2024-08-06 23:35:17 +03:00
if ( -NOT $SkipPreprocessing ) {
Update-Progress "Pre-req: Running Preprocessor..." 0
# Dot source the 'Invoke-Preprocessing' Function from 'tools/Invoke-Preprocessing.ps1' Script
$preprocessingFilePath = ".\tools\Invoke-Preprocessing.ps1"
. " $(( $workingdir -replace ( '\\$' , '' )) + '\' + ( $preprocessingFilePath -replace ( '\.\\' , '' ))) "
2024-08-07 15:30:23 -05:00
$excludedFiles = @ ( '.\.git\' , '.\.gitignore' , '.\.gitattributes' , '.\.github\CODEOWNERS' , '.\LICENSE' , " $preprocessingFilePath " , '*.png' , '*.exe' )
2024-08-06 23:35:17 +03:00
$msg = "Pre-req: Code Formatting"
Invoke-Preprocessing -WorkingDir " $workingdir " -ExcludedFiles $excludedFiles -ProgressStatusMessage $msg
}
2024-06-29 00:59:38 +03:00
2024-06-10 15:24:12 -05:00
# Create the script in memory.
2024-06-29 00:59:38 +03:00
Update-Progress "Pre-req: Allocating Memory" 0
2024-06-10 15:24:12 -05:00
$script_content = [ System.Collections.Generic.List[string] ]:: new ()
2023-03-07 12:28:00 -08:00
2024-06-29 00:59:38 +03:00
Update-Progress "Adding: Header" 5
2024-06-10 15:24:12 -05:00
$script_content . Add ( $header )
2024-06-29 00:59:38 +03:00
Update-Progress "Adding: Version" 10
2024-08-06 23:35:17 +03:00
$script_content . Add ( $ ( Get-Content " $workingdir \scripts\start.ps1" ). replace ( '#{replaceme}' , " $( Get-Date -Format yy . MM . dd ) " ))
2023-03-07 12:28:00 -08:00
2024-06-29 00:59:38 +03:00
Update-Progress "Adding: Functions" 20
2024-08-06 23:35:17 +03:00
Get-ChildItem " $workingdir \functions" -Recurse -File | ForEach-Object {
2024-06-10 15:24:12 -05:00
$script_content . Add ( $ ( Get-Content $psitem . FullName ))
}
2024-06-29 00:59:38 +03:00
Update-Progress "Adding: Config *.json" 40
2024-08-06 23:35:17 +03:00
Get-ChildItem " $workingdir \config" | Where-Object { $psitem . extension -eq ".json" } | ForEach-Object {
2024-06-10 15:24:12 -05:00
2023-03-07 12:28:00 -08:00
$json = ( Get-Content $psitem . FullName ). replace ( "'" , "''" )
2024-04-20 16:38:43 -05:00
# Replace every XML Special Character so it'll render correctly in final build
# Only do so if json files has content to be displayed (for example the applications, tweaks, features json files)
2024-07-15 03:06:00 +02:00
# Make an Array List containing every name at first level of Json File
2024-04-20 16:38:43 -05:00
$jsonAsObject = $json | convertfrom-json
2024-07-15 03:06:00 +02:00
$firstLevelJsonList = [ System.Collections.ArrayList ]:: new ()
$jsonAsObject . PSObject . Properties . Name | ForEach-Object { $null = $firstLevelJsonList . Add ( $_ )}
2024-06-29 00:59:38 +03:00
# Note:
# Avoid using HTML Entity Codes, for example '”' (stands for "Right Double Quotation Mark"),
# Use **HTML decimal/hex codes instead**, as using HTML Entity Codes will result in XML parse Error when running the compiled script.
for ( $i = 0 ; $i -lt $firstLevelJsonList . Count ; $i += 1 ) {
2024-04-20 16:38:43 -05:00
$firstLevelName = $firstLevelJsonList [ $i ]
2024-08-06 23:35:17 +03:00
if ( $jsonAsObject . $firstLevelName . content -ne $null ) {
2024-06-29 00:23:21 +03:00
$jsonAsObject . $firstLevelName . content = $jsonAsObject . $firstLevelName . content . replace ( '&' , '&' ). replace ( '“' , '“' ). replace ( '”' , '”' ). replace ( "'" , ''' ). replace ( '<' , '<' ). replace ( '>' , '>' ). replace ( '—' , '—' )
2024-04-20 16:38:43 -05:00
$jsonAsObject . $firstLevelName . content = $jsonAsObject . $firstLevelName . content . replace ( '''' , "'" ) # resolves the Double Apostrophe caused by the first replace function in the main loop
}
if ( $jsonAsObject . $firstLevelName . description -ne $null ) {
2024-06-29 00:23:21 +03:00
$jsonAsObject . $firstLevelName . description = $jsonAsObject . $firstLevelName . description . replace ( '&' , '&' ). replace ( '“' , '“' ). replace ( '”' , '”' ). replace ( "'" , ''' ). replace ( '<' , '<' ). replace ( '>' , '>' ). replace ( '—' , '—' )
2024-04-20 16:38:43 -05:00
$jsonAsObject . $firstLevelName . description = $jsonAsObject . $firstLevelName . description . replace ( '''' , "'" ) # resolves the Double Apostrophe caused by the first replace function in the main loop
2024-08-06 23:35:17 +03:00
}
}
2024-06-29 00:59:38 +03:00
# Add 'WPFInstall' as a prefix to every entry-name in 'applications.json' file
if ( $psitem . Name -eq "applications.json" ) {
for ( $i = 0 ; $i -lt $firstLevelJsonList . Count ; $i += 1 ) {
$appEntryName = $firstLevelJsonList [ $i ]
$appEntryContent = $jsonAsObject . $appEntryName
# Remove the entire app entry, so we could add it later with a different name
$jsonAsObject . PSObject . Properties . Remove ( $appEntryName )
# Add the app entry, but with a different name (WPFInstall + The App Entry Name)
$jsonAsObject | Add-Member -MemberType NoteProperty -Name "WPFInstall $appEntryName " -Value $appEntryContent
}
}
# The replace at the end is required, as without it the output of 'converto-json' will be somewhat weird for Multiline Strings
# Most Notably is the scripts in some json files, making it harder for users who want to review these scripts, which're found in the compiled script
$json = ( $jsonAsObject | convertto-json -Depth 3 ). replace ( '\r\n' , " `r`n " )
2024-04-20 16:38:43 -05:00
2024-02-21 16:06:27 -06:00
$sync . configs . $ ( $psitem . BaseName ) = $json | convertfrom-json
2024-06-10 15:24:12 -05:00
$script_content . Add ( $ ( Write-output " `$ sync.configs. $( $psitem . BaseName ) = ' $json ' `| convertfrom-json" ))
2023-03-07 12:28:00 -08:00
}
2024-08-06 23:35:17 +03:00
$xaml = ( Get-Content " $workingdir \xaml\inputXML.xaml" ). replace ( "'" , "''" )
2024-03-21 16:58:40 -07:00
2024-02-21 16:06:27 -06:00
# Dot-source the Get-TabXaml function
2024-08-06 23:35:17 +03:00
. " $workingdir \functions\private\Get-TabXaml.ps1"
2024-02-21 16:06:27 -06:00
2024-06-29 00:59:38 +03:00
Update-Progress "Building: Xaml " 75
2024-06-10 15:24:12 -05:00
$appXamlContent = Get-TabXaml "applications" 5
$tweaksXamlContent = Get-TabXaml "tweaks"
$featuresXamlContent = Get-TabXaml "feature"
2024-02-21 16:06:27 -06:00
2024-03-21 16:58:40 -07:00
2024-06-29 00:59:38 +03:00
Update-Progress "Adding: Xaml " 90
2024-03-21 16:58:40 -07:00
# Replace the placeholder in $inputXML with the content of inputApp.xaml
$xaml = $xaml -replace "{{InstallPanel_applications}}" , $appXamlContent
$xaml = $xaml -replace "{{InstallPanel_tweaks}}" , $tweaksXamlContent
$xaml = $xaml -replace "{{InstallPanel_features}}" , $featuresXamlContent
2024-06-10 15:24:12 -05:00
$script_content . Add ( $ ( Write-output " `$ inputXML = ' $xaml '" ))
2024-08-06 23:35:17 +03:00
$script_content . Add ( $ ( Get-Content " $workingdir \scripts\main.ps1" ))
2024-06-10 15:24:12 -05:00
2024-08-06 23:35:17 +03:00
if ( $Debug ) {
2024-06-29 00:59:38 +03:00
Update-Progress "Writing debug files" 95
2024-08-06 23:35:17 +03:00
$appXamlContent | Out-File -FilePath " $workingdir \xaml\inputApp.xaml" -Encoding ascii
$tweaksXamlContent | Out-File -FilePath " $workingdir \xaml\inputTweaks.xaml" -Encoding ascii
$featuresXamlContent | Out-File -FilePath " $workingdir \xaml\inputFeatures.xaml" -Encoding ascii
} else {
2024-06-29 00:59:38 +03:00
Update-Progress "Removing temporary files" 99
2024-08-06 23:35:17 +03:00
Remove-Item " $workingdir \xaml\inputApp.xaml" -ErrorAction SilentlyContinue
Remove-Item " $workingdir \xaml\inputTweaks.xaml" -ErrorAction SilentlyContinue
Remove-Item " $workingdir \xaml\inputFeatures.xaml" -ErrorAction SilentlyContinue
2024-06-10 15:24:12 -05:00
}
2024-03-21 16:58:40 -07:00
2024-08-06 23:35:17 +03:00
Set-Content -Path " $workingdir \ $scriptname " -Value ( $script_content -join " `r`n " ) -Encoding ascii
2024-06-25 21:10:16 +02:00
Write-Progress -Activity "Compiling" -Completed
2024-08-07 15:24:26 -05:00
Update-Progress -Activity "Validating" -StatusMessage "Checking winutil.ps1 Syntax" -Percent 0
try {
$null = Get-Command -Syntax .\ winutil . ps1
}
catch {
Write-Warning "Syntax Validation for 'winutil.ps1' has failed"
Write-Host " $( $Error [ 0 ]) " -ForegroundColor Red
}
Write-Progress -Activity "Validating" -Completed
2024-08-06 23:35:17 +03:00
if ( $run ) {
2024-06-25 22:05:19 +02:00
try {
2024-08-06 23:35:17 +03:00
Start-Process -FilePath "pwsh" -ArgumentList " $workingdir \ $scriptname "
} catch {
Start-Process -FilePath "powershell" -ArgumentList " $workingdir \ $scriptname "
2024-06-25 22:05:19 +02:00
}
2024-06-29 01:15:39 +03:00
2024-06-29 00:23:21 +03:00
}