NoUI mode and Concurrency edits (#4092)

* Autorun changes

* Missed a handle

* Remove todo

---------

Co-authored-by: Chris Titus <dfm.titus@gmail.com>
This commit is contained in:
KamaleiZestri
2026-02-22 17:28:55 -06:00
committed by GitHub
parent e79e946e76
commit d005a225a2
21 changed files with 208 additions and 135 deletions

View File

@@ -15,9 +15,9 @@ function Get-WinUtilSelectedPackages
) )
if ($PackageList.count -eq 1) { if ($PackageList.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
} }
$packages = [System.Collections.Hashtable]::new() $packages = [System.Collections.Hashtable]::new()

View File

@@ -4,9 +4,9 @@ function Hide-WPFInstallAppBusy {
Hides the busy overlay in the install app area of the WPF form. Hides the busy overlay in the install app area of the WPF form.
This is used to indicate that an install or uninstall has finished. This is used to indicate that an install or uninstall has finished.
#> #>
$sync.form.Dispatcher.Invoke([action]{ Invoke-WPFUIThread -ScriptBlock {
$sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Collapsed $sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Collapsed
$sync.InstallAppAreaBorder.IsEnabled = $true $sync.InstallAppAreaBorder.IsEnabled = $true
$sync.InstallAppAreaScrollViewer.Effect.Radius = 0 $sync.InstallAppAreaScrollViewer.Effect.Radius = 0
}) }
} }

View File

@@ -113,7 +113,7 @@ function Install-WinUtilProgramChoco {
[int]$totalPrograms [int]$totalPrograms
) )
$progressState = if ($currentIndex -eq $totalPrograms) { "Normal" } else { "Error" } $progressState = if ($currentIndex -eq $totalPrograms) { "Normal" } else { "Error" }
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) }
} }
function Install-ChocoPackage { function Install-ChocoPackage {
@@ -234,7 +234,7 @@ function Install-WinUtilProgramChoco {
for ($currentIndex = 0; $currentIndex -lt $totalPrograms; $currentIndex++) { for ($currentIndex = 0; $currentIndex -lt $totalPrograms; $currentIndex++) {
$Program = $Programs[$currentIndex] $Program = $Programs[$currentIndex]
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($currentIndex / $totalPrograms * 100) Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($currentIndex / $totalPrograms * 100)
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)}) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)}
switch ($Action) { switch ($Action) {
"Install" { "Install" {

View File

@@ -117,7 +117,7 @@ Function Install-WinUtilProgramWinget {
$Program = $Programs[$i] $Program = $Programs[$i]
$result = $false $result = $false
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($i / $count * 100) Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($i / $count * 100)
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i / $count)}) Invoke-WPFUIThread -ScriptBlock{ Set-WinUtilTaskbaritem -value ($i / $count)}
$result = switch ($Action) { $result = switch ($Action) {
"Install" {Invoke-Install -Program $Program} "Install" {Invoke-Install -Program $Program}

View File

@@ -8,7 +8,7 @@ function Invoke-WinUtilExplorerUpdate {
) )
if ($action -eq "refresh") { if ($action -eq "refresh") {
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ScriptBlock {
# Define the Win32 type only if it doesn't exist # Define the Win32 type only if it doesn't exist
if (-not ([System.Management.Automation.PSTypeName]'Win32').Type) { if (-not ([System.Management.Automation.PSTypeName]'Win32').Type) {
Add-Type -TypeDefinition @" Add-Type -TypeDefinition @"

View File

@@ -10,46 +10,40 @@ function Invoke-WinUtilFeatureInstall {
$CheckBox $CheckBox
) )
$x = 0 if($sync.configs.feature.$CheckBox.feature) {
Foreach( $feature in $sync.configs.feature.$CheckBox.feature ) {
$CheckBox | ForEach-Object {
if($sync.configs.feature.$psitem.feature) {
Foreach( $feature in $sync.configs.feature.$psitem.feature ) {
try { try {
Write-Host "Installing $feature" Write-Host "Installing $feature"
Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart
} catch { } catch {
if ($psitem.Exception.Message -like "*requires elevation*") { if ($CheckBox.Exception.Message -like "*requires elevation*") {
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?" Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
} else { } else {
Write-Warning "Unable to Install $feature due to unhandled exception" Write-Warning "Unable to Install $feature due to unhandled exception"
Write-Warning $psitem.Exception.StackTrace Write-Warning $CheckBox.Exception.StackTrace
} }
} }
} }
} }
if($sync.configs.feature.$psitem.InvokeScript) { if($sync.configs.feature.$CheckBox.InvokeScript) {
Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ) { Foreach( $script in $sync.configs.feature.$CheckBox.InvokeScript ) {
try { try {
$Scriptblock = [scriptblock]::Create($script) $Scriptblock = [scriptblock]::Create($script)
Write-Host "Running Script for $psitem" Write-Host "Running Script for $CheckBox"
Invoke-Command $scriptblock -ErrorAction stop Invoke-Command $scriptblock -ErrorAction stop
} catch { } catch {
if ($psitem.Exception.Message -like "*requires elevation*") { if ($CheckBox.Exception.Message -like "*requires elevation*") {
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?" Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
Write-Warning "Unable to Install $feature due to unhandled exception" Write-Warning "Unable to Install $feature due to unhandled exception"
Write-Warning $psitem.Exception.StackTrace Write-Warning $CheckBox.Exception.StackTrace
} }
} }
} }
} }
$X++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) })
}
} }

View File

@@ -14,11 +14,15 @@ function Set-WinUtilProgressbar{
[int]$Percent [int]$Percent
) )
$sync.form.Dispatcher.Invoke([action]{$sync.progressBarTextBlock.Text = $label}) if($PARAM_NOUI) {
$sync.form.Dispatcher.Invoke([action]{$sync.progressBarTextBlock.ToolTip = $label}) return;
}
Invoke-WPFUIThread -ScriptBlock {$sync.progressBarTextBlock.Text = $label}
Invoke-WPFUIThread -ScriptBlock {$sync.progressBarTextBlock.ToolTip = $label}
if ($percent -lt 5 ) { if ($percent -lt 5 ) {
$percent = 5 # Ensure the progress bar is not empty, as it looks weird $percent = 5 # Ensure the progress bar is not empty, as it looks weird
} }
$sync.form.Dispatcher.Invoke([action]{ $sync.ProgressBar.Value = $percent}) Invoke-WPFUIThread -ScriptBlock { $sync.ProgressBar.Value = $percent}
} }

View File

@@ -10,12 +10,12 @@ function Show-WPFInstallAppBusy {
param ( param (
$text = "Installing apps..." $text = "Installing apps..."
) )
$sync.form.Dispatcher.Invoke([action]{ Invoke-WPFUIThread -ScriptBlock {
$sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Visible $sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Visible
$sync.InstallAppAreaOverlay.Width = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4) $sync.InstallAppAreaOverlay.Width = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4)
$sync.InstallAppAreaOverlay.Height = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4) $sync.InstallAppAreaOverlay.Height = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4)
$sync.InstallAppAreaOverlayText.Text = $text $sync.InstallAppAreaOverlayText.Text = $text
$sync.InstallAppAreaBorder.IsEnabled = $false $sync.InstallAppAreaBorder.IsEnabled = $false
$sync.InstallAppAreaScrollViewer.Effect.Radius = 5 $sync.InstallAppAreaScrollViewer.Effect.Radius = 5
}) }
} }

View File

@@ -12,21 +12,25 @@ function Invoke-WPFFeatureInstall {
return return
} }
$handle = Invoke-WPFRunspace -ScriptBlock {
$Features = $sync.selectedFeatures $Features = $sync.selectedFeatures
Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock {
param($Features, $DebugPreference)
$sync.ProcessRunning = $true $sync.ProcessRunning = $true
if ($Features.count -eq 1) { if ($Features.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
} }
Invoke-WinUtilFeatureInstall $Features $x = 0
$Features | ForEach-Object {
Invoke-WinUtilFeatureInstall $Feature
$X++
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) }
}
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
Write-Host "===================================" Write-Host "==================================="
Write-Host "--- Features are Installed ---" Write-Host "--- Features are Installed ---"

View File

@@ -20,13 +20,13 @@ function Invoke-WPFGetInstalled {
} }
$managerPreference = $sync["ManagerPreference"] $managerPreference = $sync["ManagerPreference"]
Invoke-WPFRunspace -ParameterList @(("managerPreference", $managerPreference),("checkbox", $checkbox)) -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ParameterList @(("managerPreference", $managerPreference),("checkbox", $checkbox)) -ScriptBlock {
param ( param (
[string]$checkbox, [string]$checkbox,
[PackageManagers]$managerPreference [PackageManagers]$managerPreference
) )
$sync.ProcessRunning = $true $sync.ProcessRunning = $true
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Indeterminate" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" }
if ($checkbox -eq "winget") { if ($checkbox -eq "winget") {
Write-Host "Getting Installed Programs..." Write-Host "Getting Installed Programs..."
@@ -48,6 +48,6 @@ function Invoke-WPFGetInstalled {
Write-Host "Done..." Write-Host "Done..."
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" }
} }
} }

View File

@@ -71,9 +71,11 @@ function Invoke-WPFImpex {
# $flattenedJson = $jsonFile.PSObject.Properties.Where({ $_.Name -ne "Install" }).ForEach({ $_.Value }) # $flattenedJson = $jsonFile.PSObject.Properties.Where({ $_.Name -ne "Install" }).ForEach({ $_.Value })
$flattenedJson = $jsonFile $flattenedJson = $jsonFile
Update-WinUtilSelections -flatJson $flattenedJson Update-WinUtilSelections -flatJson $flattenedJson
# TODO test with toggles
if (!$PARAM_NOUI) {
Reset-WPFCheckBoxes -doToggles $true Reset-WPFCheckBoxes -doToggles $true
} }
}
} catch { } catch {
Write-Error "An error occurred while importing: $_" Write-Error "An error occurred while importing: $_"
} }

View File

@@ -1,13 +1,12 @@
function Invoke-WPFInstall { function Invoke-WPFInstall {
param (
[Parameter(Mandatory=$false)]
[PSObject[]]$PackagesToInstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ })
)
<# <#
.SYNOPSIS .SYNOPSIS
Installs the selected programs using winget, if one or more of the selected programs are already installed on the system, winget will try and perform an upgrade if there's a newer version to install. Installs the selected programs using winget, if one or more of the selected programs are already installed on the system, winget will try and perform an upgrade if there's a newer version to install.
#> #>
$PackagesToInstall = $sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ }
if($sync.ProcessRunning) { if($sync.ProcessRunning) {
$msg = "[Invoke-WPFInstall] An Install process is currently running." $msg = "[Invoke-WPFInstall] An Install process is currently running."
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
@@ -22,8 +21,8 @@ function Invoke-WPFInstall {
$ManagerPreference = $sync["ManagerPreference"] $ManagerPreference = $sync["ManagerPreference"]
Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ManagerPreference", $ManagerPreference)) -DebugPreference $DebugPreference -ScriptBlock { $handle = Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ManagerPreference", $ManagerPreference)) -ScriptBlock {
param($PackagesToInstall, $ManagerPreference, $DebugPreference) param($PackagesToInstall, $ManagerPreference)
$packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToInstall -Preference $ManagerPreference $packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToInstall -Preference $ManagerPreference
@@ -45,12 +44,12 @@ function Invoke-WPFInstall {
Write-Host "===========================================" Write-Host "==========================================="
Write-Host "-- Installs have finished ---" Write-Host "-- Installs have finished ---"
Write-Host "===========================================" Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
} catch { } catch {
Write-Host "===========================================" Write-Host "==========================================="
Write-Host "Error: $_" Write-Host "Error: $_"
Write-Host "===========================================" Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }
} }
$sync.ProcessRunning = $False $sync.ProcessRunning = $False
} }

View File

@@ -27,8 +27,7 @@ function Invoke-WPFRunspace {
Param ( Param (
$ScriptBlock, $ScriptBlock,
$ArgumentList, $ArgumentList,
$ParameterList, $ParameterList
$DebugPreference
) )
# Create a PowerShell instance # Create a PowerShell instance
@@ -41,7 +40,7 @@ function Invoke-WPFRunspace {
foreach ($parameter in $ParameterList) { foreach ($parameter in $ParameterList) {
$script:powershell.AddParameter($parameter[0], $parameter[1]) $script:powershell.AddParameter($parameter[0], $parameter[1])
} }
$script:powershell.AddArgument($DebugPreference) # Pass DebugPreference to the script block
$script:powershell.RunspacePool = $sync.runspace $script:powershell.RunspacePool = $sync.runspace
# Execute the RunspacePool # Execute the RunspacePool

View File

@@ -6,7 +6,7 @@ function Invoke-WPFSSHServer {
#> #>
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ScriptBlock {
Invoke-WinUtilSSHServer Invoke-WinUtilSSHServer

View File

@@ -0,0 +1,21 @@
function Invoke-WPFUIThread {
<#
.SYNOPSIS
Creates and runs a task on Winutil's WPF Forms thread.
.PARAMETER ScriptBlock
The scriptblock to invoke in the thread
#>
[CmdletBinding()]
Param (
$ScriptBlock
)
if ($PARAM_NOUI) {
return;
}
$sync.form.Dispatcher.Invoke([action]$ScriptBlock)
}

View File

@@ -32,8 +32,8 @@ function Invoke-WPFUnInstall {
$ManagerPreference = $sync["ManagerPreference"] $ManagerPreference = $sync["ManagerPreference"]
Invoke-WPFRunspace -ParameterList @(("PackagesToUninstall", $PackagesToUninstall),("ManagerPreference", $ManagerPreference)) -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ParameterList @(("PackagesToUninstall", $PackagesToUninstall),("ManagerPreference", $ManagerPreference)) -ScriptBlock {
param($PackagesToUninstall, $ManagerPreference, $DebugPreference) param($PackagesToUninstall, $ManagerPreference)
$packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToUninstall -Preference $ManagerPreference $packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToUninstall -Preference $ManagerPreference
$packagesWinget = $packagesSorted[[PackageManagers]::Winget] $packagesWinget = $packagesSorted[[PackageManagers]::Winget]
@@ -54,12 +54,12 @@ function Invoke-WPFUnInstall {
Write-Host "===========================================" Write-Host "==========================================="
Write-Host "-- Uninstalls have finished ---" Write-Host "-- Uninstalls have finished ---"
Write-Host "===========================================" Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
} catch { } catch {
Write-Host "===========================================" Write-Host "==========================================="
Write-Host "Error: $_" Write-Host "Error: $_"
Write-Host "===========================================" Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }
} }
$sync.ProcessRunning = $False $sync.ProcessRunning = $False

View File

@@ -25,30 +25,27 @@ function Invoke-WPFtweaksbutton {
Write-Debug "Number of tweaks to process: $($Tweaks.Count)" Write-Debug "Number of tweaks to process: $($Tweaks.Count)"
# The leading "," in the ParameterList is necessary because we only provide one argument and powershell cannot be convinced that we want a nested loop with only one argument otherwise # The leading "," in the ParameterList is necessary because we only provide one argument and powershell cannot be convinced that we want a nested loop with only one argument otherwise
Invoke-WPFRunspace -ParameterList @(,("tweaks",$tweaks)) -DebugPreference $DebugPreference -ScriptBlock { $handle = Invoke-WPFRunspace -ParameterList @(,("tweaks",$tweaks)) -ScriptBlock {
param( param($tweaks)
$tweaks,
$DebugPreference
)
Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)" Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)"
$sync.ProcessRunning = $true $sync.ProcessRunning = $true
if ($Tweaks.count -eq 1) { if ($Tweaks.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
} }
# Execute other selected tweaks # Execute other selected tweaks
for ($i = 0; $i -lt $Tweaks.Count; $i++) { for ($i = 0; $i -lt $Tweaks.Count; $i++) {
Set-WinUtilProgressBar -Label "Applying $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100) Set-WinUtilProgressBar -Label "Applying $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100)
Invoke-WinUtilTweaks $tweaks[$i] Invoke-WinUtilTweaks $tweaks[$i]
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$Tweaks.Count) }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($i/$Tweaks.Count) }
} }
Set-WinUtilProgressBar -Label "Tweaks finished" -Percent 100 Set-WinUtilProgressBar -Label "Tweaks finished" -Percent 100
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
Write-Host "=================================" Write-Host "================================="
Write-Host "-- Tweaks are Finished ---" Write-Host "-- Tweaks are Finished ---"
Write-Host "=================================" Write-Host "================================="

View File

@@ -20,26 +20,26 @@ function Invoke-WPFundoall {
return return
} }
Invoke-WPFRunspace -ArgumentList $tweaks -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ArgumentList $tweaks -ScriptBlock {
param($tweaks, $DebugPreference) param($tweaks)
$sync.ProcessRunning = $true $sync.ProcessRunning = $true
if ($tweaks.count -eq 1) { if ($tweaks.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
} }
for ($i = 0; $i -lt $tweaks.Count; $i++) { for ($i = 0; $i -lt $tweaks.Count; $i++) {
Set-WinUtilProgressBar -Label "Undoing $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100) Set-WinUtilProgressBar -Label "Undoing $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100)
Invoke-WinUtiltweaks $tweaks[$i] -undo $true Invoke-WinUtiltweaks $tweaks[$i] -undo $true
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$tweaks.Count) }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($i/$tweaks.Count) }
} }
Set-WinUtilProgressBar -Label "Undo Tweaks Finished" -Percent 100 Set-WinUtilProgressBar -Label "Undo Tweaks Finished" -Percent 100
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
Write-Host "==================================" Write-Host "=================================="
Write-Host "--- Undo Tweaks are Finished ---" Write-Host "--- Undo Tweaks are Finished ---"
Write-Host "==================================" Write-Host "=================================="

View File

@@ -0,0 +1,48 @@
function Invoke-WinUtilAutoRun {
<#
.SYNOPSIS
Runs Install, Tweaks, and Features with optional UI invocation.
#>
function BusyWait {
Start-Sleep -Seconds 5
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
}
BusyWait
Write-Host "Applying tweaks..."
Invoke-WPFtweaksbutton
BusyWait
Write-Host "Applying toggles..."
$handle = Invoke-WPFRunspace -ScriptBlock {
$Toggles = $sync.selectedToggles
Write-Debug "Inside Number of toggles to process: $($Toggles.Count)"
$sync.ProcessRunning = $true
for ($i = 0; $i -lt $Tweaks.Count; $i++) {
Invoke-WinUtilTweaks $Toggles[$i]
}
$sync.ProcessRunning = $false
Write-Host "================================="
Write-Host "-- Toggles are Finished ---"
Write-Host "================================="
}
BusyWait
Write-Host "Applying features..."
Invoke-WPFFeatureInstall
BusyWait
Write-Host "Installing applications..."
Invoke-WPFInstall
BusyWait
Write-Host "Done."
}

View File

@@ -13,10 +13,14 @@ $maxthreads = [int]$env:NUMBER_OF_PROCESSORS
# Create a new session state for parsing variables into our runspace # Create a new session state for parsing variables into our runspace
$hashVars = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync',$sync,$Null $hashVars = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync',$sync,$Null
$debugVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'DebugPreference',$DebugPreference,$Null
$uiVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'PARAM_NOUI',$PARAM_NOUI,$Null
$InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() $InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
# Add the variable to the session state # Add the variable to the session state
$InitialSessionState.Variables.Add($hashVars) $InitialSessionState.Variables.Add($hashVars)
$InitialSessionState.Variables.Add($debugVar)
$InitialSessionState.Variables.Add($uiVar)
# Get every private function and add them to the session state # Get every private function and add them to the session state
$functions = Get-ChildItem function:\ | Where-Object { $_.Name -imatch 'winutil|WPF' } $functions = Get-ChildItem function:\ | Where-Object { $_.Name -imatch 'winutil|WPF' }
@@ -55,6 +59,42 @@ class GenericException : Exception {
GenericException($Message) : base($Message) {} GenericException($Message) : base($Message) {}
} }
# Load the configuration files
$sync.configs.applicationsHashtable = @{}
$sync.configs.applications.PSObject.Properties | ForEach-Object {
$sync.configs.applicationsHashtable[$_.Name] = $_.Value
}
Set-PackageManagerPreference
if ($PARAM_NOUI) {
Show-CTTLogo
if ($PARAM_CONFIG -and -not [string]::IsNullOrWhiteSpace($PARAM_CONFIG)) {
Write-Host "Running config file tasks..."
Invoke-WPFImpex -type "import" -Config $PARAM_CONFIG
if ($PARAM_RUN) {
Invoke-WinUtilAutoRun
}
else {
Write-Host "Did you forget to add '--Run'?";
}
$sync.runspace.Dispose()
$sync.runspace.Close()
[System.GC]::Collect()
Stop-Transcript
exit 1
}
else {
Write-Host "Cannot automatically run without a config file provided."
$sync.runspace.Dispose()
$sync.runspace.Close()
[System.GC]::Collect()
Stop-Transcript
exit 1
}
}
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window' $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
@@ -115,12 +155,7 @@ $sync.Form.Add_Loaded({
}) })
Invoke-WinutilThemeChange -init $true Invoke-WinutilThemeChange -init $true
# Load the configuration files
$sync.configs.applicationsHashtable = @{}
$sync.configs.applications.PSObject.Properties | ForEach-Object {
$sync.configs.applicationsHashtable[$_.Name] = $_.Value
}
# Now call the function with the final merged config # Now call the function with the final merged config
Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1 Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1
@@ -144,7 +179,6 @@ $xaml.SelectNodes("//*[@Name]") | ForEach-Object {$sync["$("$($psitem.Name)")"]
#Persist Package Manager preference across winutil restarts #Persist Package Manager preference across winutil restarts
$sync.ChocoRadioButton.Add_Checked({Set-PackageManagerPreference Choco}) $sync.ChocoRadioButton.Add_Checked({Set-PackageManagerPreference Choco})
$sync.WingetRadioButton.Add_Checked({Set-PackageManagerPreference Winget}) $sync.WingetRadioButton.Add_Checked({Set-PackageManagerPreference Winget})
Set-PackageManagerPreference
switch ($sync["ManagerPreference"]) { switch ($sync["ManagerPreference"]) {
"Choco" {$sync.ChocoRadioButton.IsChecked = $true; break} "Choco" {$sync.ChocoRadioButton.IsChecked = $true; break}
@@ -341,45 +375,11 @@ $sync["Form"].Add_ContentRendered({
$sync["Form"].Focus() $sync["Form"].Focus()
# maybe this is not the best place to load and execute config file?
# maybe community can help?
if ($PARAM_CONFIG -and -not [string]::IsNullOrWhiteSpace($PARAM_CONFIG)) { if ($PARAM_CONFIG -and -not [string]::IsNullOrWhiteSpace($PARAM_CONFIG)) {
Write-Host "Running config file tasks..."
Invoke-WPFImpex -type "import" -Config $PARAM_CONFIG Invoke-WPFImpex -type "import" -Config $PARAM_CONFIG
if ($PARAM_RUN) { if ($PARAM_RUN) {
# Wait for any existing process to complete before starting Invoke-WinUtilAutoRun
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
Start-Sleep -Seconds 5
Write-Host "Applying tweaks..."
if (-not $sync.ProcessRunning) {
Invoke-WPFtweaksbutton
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
}
Start-Sleep -Seconds 5
Write-Host "Installing features..."
if (-not $sync.ProcessRunning) {
Invoke-WPFFeatureInstall
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
}
Start-Sleep -Seconds 5
Write-Host "Installing applications..."
if (-not $sync.ProcessRunning) {
Invoke-WPFInstall
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 1
}
}
Start-Sleep -Seconds 5
Write-Host "Done."
} }
} }

View File

@@ -8,7 +8,8 @@
param ( param (
[string]$Config, [string]$Config,
[switch]$Run [switch]$Run,
[switch]$Noui
) )
if ($Config) { if ($Config) {
@@ -18,10 +19,14 @@ if ($Config) {
$PARAM_RUN = $false $PARAM_RUN = $false
# Handle the -Run switch # Handle the -Run switch
if ($Run) { if ($Run) {
Write-Host "Running config file tasks..."
$PARAM_RUN = $true $PARAM_RUN = $true
} }
$PARAM_NOUI = $false
if ($Noui) {
$PARAM_NOUI = $true
}
# Load DLLs # Load DLLs
Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Windows.Forms