mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2025-01-15 17:30:37 -06:00
Refactor Compile.ps1: modularity, error handling, and logging improvements
- Moved Update-Progress function to an external script for better modularity. - Added Encode-JsonSpecialChars function to handle JSON special character encoding. - Implemented error handling with try/catch blocks during preprocessing and compilation. - Introduced logging functionality to track progress and errors. - Improved path handling using $PSScriptRoot and Join-Path for better portability.
This commit is contained in:
parent
2748767a47
commit
7e638bb92d
126
Compile.ps1
126
Compile.ps1
@ -3,29 +3,39 @@ param (
|
|||||||
[switch]$Run,
|
[switch]$Run,
|
||||||
[switch]$SkipPreprocessing
|
[switch]$SkipPreprocessing
|
||||||
)
|
)
|
||||||
|
|
||||||
$OFS = "`r`n"
|
$OFS = "`r`n"
|
||||||
$scriptname = "winutil.ps1"
|
$scriptname = "winutil.ps1"
|
||||||
$workingdir = $PSScriptRoot
|
$workingdir = $PSScriptRoot
|
||||||
|
$logFilePath = Join-Path $workingdir "compile.log"
|
||||||
|
|
||||||
# Variable to sync between runspaces
|
# Variable to sync between runspaces
|
||||||
$sync = [Hashtable]::Synchronized(@{})
|
$sync = [Hashtable]::Synchronized(@{})
|
||||||
$sync.PSScriptRoot = $workingdir
|
$sync.PSScriptRoot = $workingdir
|
||||||
$sync.configs = @{}
|
$sync.configs = @{}
|
||||||
|
|
||||||
function Update-Progress {
|
# Dot-source external functions
|
||||||
|
. "$PSScriptRoot\tools\Update-Progress.ps1"
|
||||||
|
|
||||||
|
# Function to log messages
|
||||||
|
function Log-Message {
|
||||||
|
param([string]$Message)
|
||||||
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||||
|
Add-Content -Path $logFilePath -Value "$timestamp - $Message"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to encode special characters in JSON
|
||||||
|
function Encode-JsonSpecialChars {
|
||||||
param (
|
param (
|
||||||
[Parameter(Mandatory, position=0)]
|
[Parameter(Mandatory)]
|
||||||
[string]$StatusMessage,
|
[PSObject]$jsonObject
|
||||||
|
|
||||||
[Parameter(Mandatory, position=1)]
|
|
||||||
[ValidateRange(0,100)]
|
|
||||||
[int]$Percent,
|
|
||||||
|
|
||||||
[Parameter(position=2)]
|
|
||||||
[string]$Activity = "Compiling"
|
|
||||||
)
|
)
|
||||||
|
foreach ($prop in $jsonObject.PSObject.Properties) {
|
||||||
Write-Progress -Activity $Activity -Status $StatusMessage -PercentComplete $Percent
|
if ($prop.Value -is [string]) {
|
||||||
|
$prop.Value = $prop.Value.Replace('&','&').Replace('“','“').Replace('”','”').Replace("'",''').Replace('<','<').Replace('>','>').Replace('—','—')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $jsonObject
|
||||||
}
|
}
|
||||||
|
|
||||||
$header = @"
|
$header = @"
|
||||||
@ -36,16 +46,25 @@ $header = @"
|
|||||||
################################################################################################################
|
################################################################################################################
|
||||||
"@
|
"@
|
||||||
|
|
||||||
|
if ($Debug) {
|
||||||
|
Write-Debug "Debug mode enabled"
|
||||||
|
}
|
||||||
|
|
||||||
if (-NOT $SkipPreprocessing) {
|
if (-NOT $SkipPreprocessing) {
|
||||||
Update-Progress "Pre-req: Running Preprocessor..." 0
|
try {
|
||||||
|
Update-Progress "Pre-req: Running Preprocessor..." 0
|
||||||
|
$preprocessingFilePath = Join-Path $PSScriptRoot "tools\Invoke-Preprocessing.ps1"
|
||||||
|
. "$preprocessingFilePath"
|
||||||
|
|
||||||
# Dot source the 'Invoke-Preprocessing' Function from 'tools/Invoke-Preprocessing.ps1' Script
|
$excludedFiles = @('.\.git\', '.\.gitignore', '.\.gitattributes', '.\.github\CODEOWNERS', '.\LICENSE', "$preprocessingFilePath", '*.png', '*.exe')
|
||||||
$preprocessingFilePath = ".\tools\Invoke-Preprocessing.ps1"
|
$msg = "Pre-req: Code Formatting"
|
||||||
. "$(($workingdir -replace ('\\$', '')) + '\' + ($preprocessingFilePath -replace ('\.\\', '')))"
|
Invoke-Preprocessing -WorkingDir "$workingdir" -ExcludedFiles $excludedFiles -ProgressStatusMessage $msg
|
||||||
|
}
|
||||||
$excludedFiles = @('.\.git\', '.\.gitignore', '.\.gitattributes', '.\.github\CODEOWNERS', '.\LICENSE', "$preprocessingFilePath", '*.png', '*.exe')
|
catch {
|
||||||
$msg = "Pre-req: Code Formatting"
|
Write-Error "Preprocessing failed: $($_.Exception.Message)"
|
||||||
Invoke-Preprocessing -WorkingDir "$workingdir" -ExcludedFiles $excludedFiles -ProgressStatusMessage $msg
|
Log-Message "Preprocessing failed: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create the script in memory.
|
# Create the script in memory.
|
||||||
@ -61,71 +80,43 @@ $script_content.Add($(Get-Content "$workingdir\scripts\start.ps1").replace('#{re
|
|||||||
Update-Progress "Adding: Functions" 20
|
Update-Progress "Adding: Functions" 20
|
||||||
Get-ChildItem "$workingdir\functions" -Recurse -File | ForEach-Object {
|
Get-ChildItem "$workingdir\functions" -Recurse -File | ForEach-Object {
|
||||||
$script_content.Add($(Get-Content $psitem.FullName))
|
$script_content.Add($(Get-Content $psitem.FullName))
|
||||||
}
|
}
|
||||||
|
|
||||||
Update-Progress "Adding: Config *.json" 40
|
Update-Progress "Adding: Config *.json" 40
|
||||||
Get-ChildItem "$workingdir\config" | Where-Object {$psitem.extension -eq ".json"} | ForEach-Object {
|
Get-ChildItem "$workingdir\config" | Where-Object {$_.extension -eq ".json"} | ForEach-Object {
|
||||||
|
$json = Get-Content -Path $psitem.FullName -Raw
|
||||||
|
$jsonAsObject = $json | ConvertFrom-Json
|
||||||
|
$jsonAsObject = Encode-JsonSpecialChars -jsonObject $jsonAsObject
|
||||||
|
|
||||||
$json = (Get-Content $psitem.FullName).replace("'","''")
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
# Make an Array List containing every name at first level of Json File
|
|
||||||
$jsonAsObject = $json | convertfrom-json
|
|
||||||
$firstLevelJsonList = [System.Collections.ArrayList]::new()
|
|
||||||
$jsonAsObject.PSObject.Properties.Name | ForEach-Object {$null = $firstLevelJsonList.Add($_)}
|
|
||||||
# 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) {
|
|
||||||
$firstLevelName = $firstLevelJsonList[$i]
|
|
||||||
if ($jsonAsObject.$firstLevelName.content -ne $null) {
|
|
||||||
$jsonAsObject.$firstLevelName.content = $jsonAsObject.$firstLevelName.content.replace('&','&').replace('“','“').replace('”','”').replace("'",''').replace('<','<').replace('>','>').replace('—','—')
|
|
||||||
$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) {
|
|
||||||
$jsonAsObject.$firstLevelName.description = $jsonAsObject.$firstLevelName.description.replace('&','&').replace('“','“').replace('”','”').replace("'",''').replace('<','<').replace('>','>').replace('—','—')
|
|
||||||
$jsonAsObject.$firstLevelName.description = $jsonAsObject.$firstLevelName.description.replace('''',"'") # resolves the Double Apostrophe caused by the first replace function in the main loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add 'WPFInstall' as a prefix to every entry-name in 'applications.json' file
|
|
||||||
if ($psitem.Name -eq "applications.json") {
|
if ($psitem.Name -eq "applications.json") {
|
||||||
for ($i = 0; $i -lt $firstLevelJsonList.Count; $i += 1) {
|
foreach ($appEntryName in $jsonAsObject.PSObject.Properties.Name) {
|
||||||
$appEntryName = $firstLevelJsonList[$i]
|
|
||||||
$appEntryContent = $jsonAsObject.$appEntryName
|
$appEntryContent = $jsonAsObject.$appEntryName
|
||||||
# Remove the entire app entry, so we could add it later with a different name
|
|
||||||
$jsonAsObject.PSObject.Properties.Remove($appEntryName)
|
$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
|
$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
|
$json = ($jsonAsObject | ConvertTo-Json -Depth 3).replace('\r\n', "`r`n")
|
||||||
# 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
|
$sync.configs.$($psitem.BaseName) = $json | ConvertFrom-Json
|
||||||
$json = ($jsonAsObject | convertto-json -Depth 3).replace('\r\n',"`r`n")
|
$script_content.Add("`$sync.configs.$($psitem.BaseName) = '$json' | ConvertFrom-Json")
|
||||||
|
|
||||||
$sync.configs.$($psitem.BaseName) = $json | convertfrom-json
|
|
||||||
$script_content.Add($(Write-output "`$sync.configs.$($psitem.BaseName) = '$json' `| convertfrom-json" ))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$xaml = (Get-Content "$workingdir\xaml\inputXML.xaml").replace("'","''")
|
$xaml = (Get-Content "$workingdir\xaml\inputXML.xaml" -Raw).Replace("'","''")
|
||||||
|
|
||||||
# Dot-source the Get-TabXaml function
|
# Dot-source the Get-TabXaml function
|
||||||
. "$workingdir\functions\private\Get-TabXaml.ps1"
|
. "$workingdir\functions\private\Get-TabXaml.ps1"
|
||||||
|
|
||||||
Update-Progress "Building: Xaml " 75
|
Update-Progress "Building: Xaml" 75
|
||||||
$appXamlContent = Get-TabXaml "applications" 5
|
$appXamlContent = Get-TabXaml "applications" 5
|
||||||
$tweaksXamlContent = Get-TabXaml "tweaks"
|
$tweaksXamlContent = Get-TabXaml "tweaks"
|
||||||
$featuresXamlContent = Get-TabXaml "feature"
|
$featuresXamlContent = Get-TabXaml "feature"
|
||||||
|
|
||||||
|
Update-Progress "Adding: Xaml" 90
|
||||||
Update-Progress "Adding: Xaml " 90
|
|
||||||
# Replace the placeholder in $inputXML with the content of inputApp.xaml
|
|
||||||
$xaml = $xaml -replace "{{InstallPanel_applications}}", $appXamlContent
|
$xaml = $xaml -replace "{{InstallPanel_applications}}", $appXamlContent
|
||||||
$xaml = $xaml -replace "{{InstallPanel_tweaks}}", $tweaksXamlContent
|
$xaml = $xaml -replace "{{InstallPanel_tweaks}}", $tweaksXamlContent
|
||||||
$xaml = $xaml -replace "{{InstallPanel_features}}", $featuresXamlContent
|
$xaml = $xaml -replace "{{InstallPanel_features}}", $featuresXamlContent
|
||||||
|
|
||||||
$script_content.Add($(Write-output "`$inputXML = '$xaml'"))
|
$script_content.Add("`$inputXML = '$xaml'")
|
||||||
|
|
||||||
$script_content.Add($(Get-Content "$workingdir\scripts\main.ps1"))
|
$script_content.Add($(Get-Content "$workingdir\scripts\main.ps1"))
|
||||||
|
|
||||||
@ -146,19 +137,22 @@ Write-Progress -Activity "Compiling" -Completed
|
|||||||
|
|
||||||
Update-Progress -Activity "Validating" -StatusMessage "Checking winutil.ps1 Syntax" -Percent 0
|
Update-Progress -Activity "Validating" -StatusMessage "Checking winutil.ps1 Syntax" -Percent 0
|
||||||
try {
|
try {
|
||||||
$null = Get-Command -Syntax .\winutil.ps1
|
$null = Get-Command -Syntax ".\winutil.ps1"
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Warning "Syntax Validation for 'winutil.ps1' has failed"
|
Write-Warning "Syntax Validation for 'winutil.ps1' has failed"
|
||||||
Write-Host "$($Error[0])" -ForegroundColor Red
|
Write-Host "$($Error[0])" -ForegroundColor Red
|
||||||
|
Log-Message "Syntax Validation failed: $($Error[0])"
|
||||||
}
|
}
|
||||||
Write-Progress -Activity "Validating" -Completed
|
Write-Progress -Activity "Validating" -Completed
|
||||||
|
|
||||||
if ($run) {
|
if ($Run) {
|
||||||
try {
|
try {
|
||||||
Start-Process -FilePath "pwsh" -ArgumentList "$workingdir\$scriptname"
|
Start-Process -FilePath "pwsh" -ArgumentList "$workingdir\$scriptname"
|
||||||
} catch {
|
}
|
||||||
|
catch {
|
||||||
Start-Process -FilePath "powershell" -ArgumentList "$workingdir\$scriptname"
|
Start-Process -FilePath "powershell" -ArgumentList "$workingdir\$scriptname"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log-Message "Compilation completed"
|
||||||
|
Loading…
Reference in New Issue
Block a user