diff --git a/functions/public/Invoke-WPFRunspace.ps1 b/functions/public/Invoke-WPFRunspace.ps1 index 440a13b7..b7db9289 100644 --- a/functions/public/Invoke-WPFRunspace.ps1 +++ b/functions/public/Invoke-WPFRunspace.ps1 @@ -20,31 +20,52 @@ function Invoke-WPFRunspace { [CmdletBinding()] Param ( - $ScriptBlock, - $ArgumentList, - $DebugPreference + [Parameter(Mandatory=$true)] + [scriptblock]$ScriptBlock, + [Parameter(Mandatory=$false)] + [object[]]$ArgumentList, + [Parameter(Mandatory=$false)] + [System.Management.Automation.ActionPreference]$DebugPreference = 'SilentlyContinue' ) - # Create a PowerShell instance - $script:powershell = [powershell]::Create() + try { + # Create a PowerShell instance + $powershell = [powershell]::Create() - # Add Scriptblock and Arguments to runspace - $script:powershell.AddScript($ScriptBlock) - foreach ($Argument in $ArgumentList) { - $script:powershell.AddArgument($Argument) + # Add Scriptblock and Arguments to runspace + $powershell.AddScript($ScriptBlock) + if ($ArgumentList) { + foreach ($Argument in $ArgumentList) { + $powershell.AddArgument($Argument) + } + } + $powershell.AddArgument($DebugPreference) + + # Ensure runspace pool is available + if (-not $sync.runspace -or $sync.runspace.IsDisposed) { + throw "Runspace pool is not initialized or has been disposed." + } + $powershell.RunspacePool = $sync.runspace + + # Execute the RunspacePool asynchronously + $handle = $powershell.BeginInvoke() + + # Set up an event to handle completion + $null = Register-ObjectEvent -InputObject $powershell -EventName InvocationStateChanged -Action { + if ($EventArgs.InvocationStateInfo.State -eq "Completed") { + $powershell.EndInvoke($handle) + $powershell.Dispose() + [System.GC]::Collect() + Unregister-Event -SourceIdentifier $EventSubscriber.SourceIdentifier + } + } + + # Return the handle + return $handle } - $script:powershell.AddArgument($DebugPreference) # Pass DebugPreference to the script block - $script:powershell.RunspacePool = $sync.runspace - - # Execute the RunspacePool - $script:handle = $script:powershell.BeginInvoke() - - # Clean up the RunspacePool threads when they are complete, and invoke the garbage collector to clean up the memory - if ($script:handle.IsCompleted) { - $script:powershell.EndInvoke($script:handle) - $script:powershell.Dispose() - $sync.runspace.Dispose() - $sync.runspace.Close() - [System.GC]::Collect() + catch { + Write-Error "Error in Invoke-WPFRunspace: $_" + if ($powershell) { $powershell.Dispose() } + throw } } diff --git a/functions/public/Invoke-WPFtweaksbutton.ps1 b/functions/public/Invoke-WPFtweaksbutton.ps1 index a4f38193..7657437a 100644 --- a/functions/public/Invoke-WPFtweaksbutton.ps1 +++ b/functions/public/Invoke-WPFtweaksbutton.ps1 @@ -13,45 +13,66 @@ function Invoke-WPFtweaksbutton { } $Tweaks = (Get-WinUtilCheckBoxes)["WPFTweaks"] + $DNSChange = $sync["WPFchangedns"].text -ne "Default" - Set-WinUtilDNS -DNSProvider $sync["WPFchangedns"].text + if ($DNSChange) { + Set-WinUtilDNS -DNSProvider $sync["WPFchangedns"].text + } - if ($tweaks.count -eq 0 -and $sync["WPFchangedns"].text -eq "Default") { - $msg = "Please check the tweaks you wish to perform." + if ($tweaks.count -eq 0 -and -not $DNSChange) { + $msg = "Please check the tweaks you wish to perform or select a DNS provider." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } Write-Debug "Number of tweaks to process: $($Tweaks.Count)" - Invoke-WPFRunspace -ArgumentList $Tweaks -DebugPreference $DebugPreference -ScriptBlock { - param($Tweaks, $DebugPreference) - Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)" + try { + $handle = Invoke-WPFRunspace -ArgumentList $Tweaks, $DNSChange -DebugPreference $DebugPreference -ScriptBlock { + param($Tweaks, $DNSChange, $DebugPreference) + Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)" - $sync.ProcessRunning = $true + $sync.ProcessRunning = $true - if ($Tweaks.count -eq 1) { - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) - } else { - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) + if ($Tweaks.count -eq 0 -and $DNSChange) { + $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) + } elseif ($Tweaks.count -eq 1) { + $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) + } else { + $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) + } + + # Execute selected tweaks + for ($i = 0; $i -lt $Tweaks.Count; $i++) { + $currentTweak = $Tweaks[$i] + Set-WinUtilProgressBar -Label "Applying $currentTweak" -Percent ($i / $Tweaks.Count * 100) + + # Apply the current tweak + Invoke-WinUtilTweaks $currentTweak + + # Update taskbar progress + $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value (($i + 1) / $Tweaks.Count) }) + } + + Set-WinUtilProgressBar -Label "Tweaks finished" -Percent 100 + $sync.ProcessRunning = $false + $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) + Write-Host "=================================" + Write-Host "-- Tweaks are Finished ---" + Write-Host "=================================" } - # Execute other selected tweaks - for ($i = 0; $i -lt $Tweaks.Count; $i++) { - Set-WinUtilProgressBar -Label "Applying $($tweaks[$i])" -Percent ($i / $Tweaks.Count * 100) - Invoke-WinUtilTweaks $tweaks[$i]$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$Tweaks.Count) }) - } - Set-WinUtilProgressBar -Label "Tweaks finished" -Percent 100 - $sync.ProcessRunning = $false - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }) - Write-Host "=================================" - Write-Host "-- Tweaks are Finished ---" - Write-Host "=================================" + # Optionally, you can add code here to update the UI or perform other tasks while the runspace is executing + # For example, you might want to disable certain UI elements until the runspace completes - # $ButtonType = [System.Windows.MessageBoxButton]::OK - # $MessageboxTitle = "Tweaks are Finished " - # $Messageboxbody = ("Done") - # $MessageIcon = [System.Windows.MessageBoxImage]::Information - # [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) + # If you need to wait for completion before proceeding, you can use: + # $handle.AsyncWaitHandle.WaitOne() + # But be cautious about blocking the UI thread + + Write-Host "Tweaks execution started in background." + } + catch { + Write-Error "Failed to start tweaks execution: $_" + [System.Windows.MessageBox]::Show("An error occurred while starting tweaks execution. Please check the logs for more information.", "Error", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) } }