2026-06-04 00:09:44 +03:00
Write-Host @"
CCCCCCCCCCCCCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
CCC::::::::::::CT:::::::::::::::::::::TT:::::::::::::::::::::T
CC:::::::::::::::CT:::::::::::::::::::::TT:::::::::::::::::::::T
C:::::CCCCCCCC::::CT:::::TT:::::::TT:::::TT:::::TT:::::::TT:::::T
C:::::C CCCCCCTTTTTT T:::::T TTTTTTTTTTTT T:::::T TTTTTT
C:::::C T:::::T T:::::T
C:::::C T:::::T T:::::T
C:::::C T:::::T T:::::T
C:::::C T:::::T T:::::T
C:::::C T:::::T T:::::T
C:::::C T:::::T T:::::T
C:::::C CCCCCC T:::::T T:::::T
C:::::CCCCCCCC::::C TT:::::::TT TT:::::::TT
CC:::::::::::::::C T:::::::::T T:::::::::T
CCC::::::::::::C T:::::::::T T:::::::::T
CCCCCCCCCCCCC TTTTTTTTTTT TTTTTTTTTTT
====Chris Titus Tech=====
=====Windows Toolbox=====
"@
2025-04-14 13:33:16 -05:00
# Create enums
Add-Type @"
public enum PackageManagers
{
Winget,
Choco
}
"@
2023-07-27 16:06:41 -05:00
# SPDX-License-Identifier: MIT
2023-10-19 17:12:55 -05:00
# Set the maximum number of threads for the RunspacePool to the number of threads on the machine
2023-05-09 13:14:27 -05:00
$maxthreads = [ int ] $env:NUMBER_OF_PROCESSORS
2023-10-19 17:12:55 -05:00
# Create a new session state for parsing variables into our runspace
2023-05-09 13:14:27 -05:00
$hashVars = New-object System . Management . Automation . Runspaces . SessionStateVariableEntry -ArgumentList 'sync' , $sync , $Null
2026-03-04 12:21:18 -06:00
$offlineVar = New-object System . Management . Automation . Runspaces . SessionStateVariableEntry -ArgumentList 'PARAM_OFFLINE' , $PARAM_OFFLINE , $Null
2023-05-09 13:14:27 -05:00
$InitialSessionState = [ System.Management.Automation.Runspaces.InitialSessionState ]:: CreateDefault ()
2023-10-19 17:12:55 -05:00
# Add the variable to the session state
2023-05-09 13:14:27 -05:00
$InitialSessionState . Variables . Add ( $hashVars )
2026-03-04 12:21:18 -06:00
$InitialSessionState . Variables . Add ( $offlineVar )
2023-05-09 13:14:27 -05:00
2023-10-19 17:12:55 -05:00
# Get every private function and add them to the session state
2026-02-06 18:29:10 +02:00
$functions = Get-ChildItem function : \ | Where-Object { $_ . Name -imatch 'winutil|WPF' }
2024-08-06 23:35:17 +03:00
foreach ( $function in $functions ) {
2023-05-09 13:14:27 -05:00
$functionDefinition = Get-Content function : \ $ ( $function . name )
$functionEntry = New-Object System . Management . Automation . Runspaces . SessionStateFunctionEntry -ArgumentList $ ( $function . name ), $functionDefinition
2023-10-19 17:12:55 -05:00
2023-05-09 13:14:27 -05:00
$initialSessionState . Commands . Add ( $functionEntry )
}
2023-10-19 17:12:55 -05:00
# Create the runspace pool
$sync . runspace = [ runspacefactory ]:: CreateRunspacePool (
1 , # Minimum thread count
$maxthreads , # Maximum thread count
$InitialSessionState , # Initial session state
$Host # Machine to create runspaces on
)
2023-05-09 13:14:27 -05:00
2023-10-19 17:12:55 -05:00
# Open the RunspacePool instance
2023-05-09 13:14:27 -05:00
$sync . runspace . Open ()
2023-10-19 17:12:55 -05:00
# Create classes for different exceptions
2023-03-07 12:28:00 -08:00
2024-12-06 06:22:33 +03:00
class WingetFailedInstall : Exception {
[ string ] $additionalData
WingetFailedInstall ( $Message ) : base ( $Message ) {}
}
2023-03-07 12:28:00 -08:00
2024-12-06 06:22:33 +03:00
class ChocoFailedInstall : Exception {
[ string ] $additionalData
ChocoFailedInstall ( $Message ) : base ( $Message ) {}
}
2023-03-07 12:28:00 -08:00
2024-12-06 06:22:33 +03:00
class GenericException : Exception {
[ string ] $additionalData
GenericException ( $Message ) : base ( $Message ) {}
}
2023-10-19 17:12:55 -05:00
2026-02-22 17:28:55 -06:00
# Load the configuration files
$sync . configs . applicationsHashtable = @ {}
$sync . configs . applications . PSObject . Properties | ForEach-Object {
$sync . configs . applicationsHashtable [ $_ . Name ] = $_ . Value
}
2026-03-02 13:05:43 -06:00
Set-Preferences
2026-02-22 17:28:55 -06:00
2026-05-26 13:22:28 -07:00
if ( $Preset ) {
# Selects the tweaks from $Preset varible
Update-WinUtilSelections -flatJson $sync . configs . preset . $Preset
# Run tweaks that were selected by Update-WinUtilSelections
Invoke-WinUtilAutoRun
# Cleanup and exit
$sync . runspace . Dispose ()
$sync . runspace . Close ()
[ System.GC ]:: Collect ()
Stop-Transcript
return
}
2026-06-08 18:02:35 +03:00
if ( $Config ) {
Invoke-WPFImpex -type "import" -Config $Config
Invoke-WinUtilAutoRun
# Cleanup and exit
$sync . runspace . Dispose ()
$sync . runspace . Close ()
[ System.GC ]:: Collect ()
Stop-Transcript
return
2026-02-22 17:28:55 -06:00
}
2023-03-07 12:28:00 -08:00
$inputXML = $inputXML -replace 'mc:Ignorable="d"' , '' -replace "x:N" , 'N' -replace '^<Win.*' , '<Window'
2023-07-27 16:06:41 -05:00
2023-03-07 12:28:00 -08:00
[ void][System.Reflection.Assembly ]:: LoadWithPartialName ( 'presentationframework' )
[ xml ] $XAML = $inputXML
2023-10-19 17:12:55 -05:00
# Read the XAML file
2024-08-28 19:08:39 +03:00
$readerOperationSuccessful = $false # There's more cases of failure then success.
2023-03-07 12:28:00 -08:00
$reader = ( New-Object System . Xml . XmlNodeReader $xaml )
2024-07-08 22:59:58 +03:00
try {
$sync [ "Form" ] = [ Windows.Markup.XamlReader ]:: Load ( $reader )
2024-08-28 19:08:39 +03:00
$readerOperationSuccessful = $true
2024-07-08 22:59:58 +03:00
} catch [ System.Management.Automation.MethodInvocationException ] {
2024-08-29 00:55:40 +03:00
Write-Host "We ran into a problem with the XAML code. Check the syntax for this control..." -ForegroundColor Red
2023-03-07 12:28:00 -08:00
Write-Host $error [ 0 ]. Exception . Message -ForegroundColor Red
2024-07-08 22:59:58 +03:00
2023-03-07 12:28:00 -08:00
If ( $error [ 0 ]. Exception . Message -like "*button*" ) {
2024-08-29 00:55:40 +03:00
write-Host "Ensure your <button in the `$ inputXML does NOT have a Click=ButtonClick property. PS can't handle this `n`n`n`n " -ForegroundColor Red
2023-03-07 12:28:00 -08:00
}
2024-07-08 22:59:58 +03:00
} catch {
2024-08-29 00:55:40 +03:00
Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed." -ForegroundColor Red
2023-03-07 12:28:00 -08:00
}
2024-08-28 19:08:39 +03:00
if ( -NOT ( $readerOperationSuccessful )) {
Write-Host "Failed to parse xaml content using Windows.Markup.XamlReader's Load Method." -ForegroundColor Red
Write-Host "Quitting winutil..." -ForegroundColor Red
$sync . runspace . Dispose ()
$sync . runspace . Close ()
[ System.GC ]:: Collect ()
exit 1
}
2024-09-21 17:01:02 +02:00
# Setup the Window to follow listen for windows Theme Change events and update the winutil theme
# throttle logic needed, because windows seems to send more than one theme change event per change
$lastThemeChangeTime = [ datetime ]:: MinValue
$debounceInterval = [ timespan ]:: FromSeconds ( 2 )
$sync . Form . Add_Loaded ({
$interopHelper = New-Object System . Windows . Interop . WindowInteropHelper $sync . Form
$hwndSource = [ System.Windows.Interop.HwndSource ]:: FromHwnd ( $interopHelper . Handle )
$hwndSource . AddHook ({
param (
[ System.IntPtr ] $hwnd ,
[ int ] $msg ,
[ System.IntPtr ] $wParam ,
[ System.IntPtr ] $lParam ,
[ ref ] $handled
)
# Check for the Event WM_SETTINGCHANGE (0x1001A) and validate that Button shows the icon for "Auto" => [char]0xF08C
if (( $msg -eq 0x001A ) -and $sync . ThemeButton . Content -eq [ char ] 0xF08C ) {
$currentTime = [ datetime ]:: Now
if ( $currentTime - $lastThemeChangeTime -gt $debounceInterval ) {
Invoke-WinutilThemeChange -theme "Auto"
$script:lastThemeChangeTime = $currentTime
$handled = $true
}
}
return 0
})
})
2026-03-02 13:05:43 -06:00
Invoke-WinutilThemeChange -theme $sync . preferences . theme
2025-03-01 20:50:12 +01:00
# Now call the function with the final merged config
Invoke-WPFUIElements -configVariable $sync . configs . appnavigation -targetGridName "appscategory" -columncount 1
2025-05-12 22:45:57 +02:00
Initialize-WPFUI -targetGridName "appscategory"
2025-04-02 22:54:44 +02:00
2025-05-12 22:45:57 +02:00
Initialize-WPFUI -targetGridName "appspanel"
2025-03-01 20:50:12 +01:00
2024-08-29 00:55:40 +03:00
Invoke-WPFUIElements -configVariable $sync . configs . tweaks -targetGridName "tweakspanel" -columncount 2
2025-04-02 22:54:44 +02:00
2024-08-29 00:55:40 +03:00
Invoke-WPFUIElements -configVariable $sync . configs . feature -targetGridName "featurespanel" -columncount 2
2025-04-02 22:54:44 +02:00
2024-12-05 21:18:46 -06:00
# Future implementation: Add Windows Version to updates panel
#Invoke-WPFUIElements -configVariable $sync.configs.updates -targetGridName "updatespanel" -columncount 1
2024-08-29 00:55:40 +03:00
2023-03-07 12:28:00 -08:00
#===========================================================================
# Store Form Objects In PowerShell
#===========================================================================
2023-05-09 13:14:27 -05:00
$xaml . SelectNodes ( "//*[@Name]" ) | ForEach-Object { $sync [ " $( " $( $psitem . Name ) " ) " ] = $sync [ "Form" ]. FindName ( $psitem . Name )}
2023-03-07 12:28:00 -08:00
2025-04-14 13:33:16 -05:00
#Persist Package Manager preference across winutil restarts
2026-03-02 13:05:43 -06:00
$sync . ChocoRadioButton . Add_Checked ({
$sync . preferences . packagemanager = [ PackageManagers ]:: Choco
Set-Preferences -save
})
$sync . WingetRadioButton . Add_Checked ({
$sync . preferences . packagemanager = [ PackageManagers ]:: Winget
Set-Preferences -save
})
2025-04-14 13:33:16 -05:00
2026-03-02 13:05:43 -06:00
switch ( $sync . preferences . packagemanager ) {
2025-04-14 13:33:16 -05:00
"Choco" { $sync . ChocoRadioButton . IsChecked = $true ; break }
"Winget" { $sync . WingetRadioButton . IsChecked = $true ; break }
2024-09-10 20:02:22 +02:00
}
2023-05-09 13:14:27 -05:00
$sync . keys | ForEach-Object {
2024-08-06 23:35:17 +03:00
if ( $sync . $psitem ) {
if ( $ ( $sync [ " $psitem " ]. GetType () | Select-Object -ExpandProperty Name ) -eq "ToggleButton" ) {
2023-11-28 16:11:11 -06:00
$sync [ " $psitem " ]. Add_Click ({
[ System.Object ] $Sender = $args [ 0 ]
Invoke-WPFButton $Sender . name
})
}
2023-07-27 16:06:41 -05:00
2024-08-06 23:35:17 +03:00
if ( $ ( $sync [ " $psitem " ]. GetType () | Select-Object -ExpandProperty Name ) -eq "Button" ) {
2023-07-27 16:06:41 -05:00
$sync [ " $psitem " ]. Add_Click ({
[ System.Object ] $Sender = $args [ 0 ]
2024-01-12 00:34:41 -06:00
Invoke-WPFButton $Sender . name
2023-07-27 16:06:41 -05:00
})
}
2024-01-12 00:34:41 -06:00
if ( $ ( $sync [ " $psitem " ]. GetType () | Select-Object -ExpandProperty Name ) -eq "TextBlock" ) {
if ( $sync [ " $psitem " ]. Name . EndsWith ( "Link" )) {
$sync [ " $psitem " ]. Add_MouseUp ({
[ System.Object ] $Sender = $args [ 0 ]
Start-Process $Sender . ToolTip -ErrorAction Stop
})
}
2024-02-02 16:22:08 -06:00
2024-01-12 00:34:41 -06:00
}
2023-07-27 16:06:41 -05:00
}
}
2023-03-07 12:28:00 -08:00
#===========================================================================
# Setup background config
#===========================================================================
2023-10-19 17:12:55 -05:00
# Load computer information in the background
2023-03-07 12:28:00 -08:00
Invoke-WPFRunspace -ScriptBlock {
2024-08-06 23:35:17 +03:00
try {
2024-06-25 21:10:16 +02:00
$ProgressPreference = "SilentlyContinue"
$sync . ConfigLoaded = $False
$sync . ComputerInfo = Get-ComputerInfo
$sync . ConfigLoaded = $True
}
finally {
2025-05-05 17:06:45 +02:00
$ProgressPreference = $oldProgressPreference
2024-06-25 21:10:16 +02:00
}
2024-06-29 01:15:39 +03:00
2023-03-07 12:28:00 -08:00
} | Out-Null
#===========================================================================
2023-10-19 17:12:55 -05:00
# Setup and Show the Form
2023-03-07 12:28:00 -08:00
#===========================================================================
2024-07-25 23:19:45 +02:00
# Progress bar in taskbaritem > Set-WinUtilProgressbar
$sync [ "Form" ]. TaskbarItemInfo = New-Object System . Windows . Shell . TaskbarItemInfo
Set-WinUtilTaskbaritem -state "None"
2023-10-19 17:12:55 -05:00
# Set the titlebar
2023-05-09 13:14:27 -05:00
$sync [ "Form" ]. title = $sync [ "Form" ]. title + " " + $sync . version
2023-10-19 17:12:55 -05:00
# Set the commands that will run when the form is closed
2023-05-09 13:14:27 -05:00
$sync [ "Form" ]. Add_Closing ({
$sync . runspace . Dispose ()
$sync . runspace . Close ()
[ System.GC ]:: Collect ()
})
2024-01-12 00:34:41 -06:00
# Attach the event handler to the Click event
2024-07-08 22:59:58 +03:00
$sync . SearchBarClearButton . Add_Click ({
$sync . SearchBar . Text = ""
$sync . SearchBarClearButton . Visibility = "Collapsed"
2025-05-05 20:45:51 +05:30
# Focus the search bar after clearing the text
$sync . SearchBar . Focus ()
$sync . SearchBar . SelectAll ()
2024-01-12 00:34:41 -06:00
})
2023-11-28 16:11:11 -06:00
# add some shortcuts for people that don't like clicking
$commonKeyEvents = {
2025-05-05 17:12:57 +02:00
# Prevent shortcuts from executing if a process is already running
2023-11-28 16:11:11 -06:00
if ( $sync . ProcessRunning -eq $true ) {
return
}
2025-05-05 17:12:57 +02:00
# Handle key presses of single keys
switch ( $_ . Key ) {
"Escape" { $sync . SearchBar . Text = "" }
2023-11-28 16:11:11 -06:00
}
2025-05-05 17:12:57 +02:00
# Handle Alt key combinations for navigation
2023-11-28 16:11:11 -06:00
if ( $_ . KeyboardDevice . Modifiers -eq "Alt" ) {
2025-05-05 17:12:57 +02:00
$keyEventArgs = $_
switch ( $_ . SystemKey ) {
"I" { Invoke-WPFButton "WPFTab1BT" ; $keyEventArgs . Handled = $true } # Navigate to Install tab and suppress Windows Warning Sound
"T" { Invoke-WPFButton "WPFTab2BT" ; $keyEventArgs . Handled = $true } # Navigate to Tweaks tab
"C" { Invoke-WPFButton "WPFTab3BT" ; $keyEventArgs . Handled = $true } # Navigate to Config tab
"U" { Invoke-WPFButton "WPFTab4BT" ; $keyEventArgs . Handled = $true } # Navigate to Updates tab
2026-02-24 15:28:49 -06:00
"W" { Invoke-WPFButton "WPFTab5BT" ; $keyEventArgs . Handled = $true } # Navigate to Win11ISO tab
2024-01-12 00:34:41 -06:00
}
2023-11-28 16:11:11 -06:00
}
2025-05-05 17:12:57 +02:00
# Handle Ctrl key combinations for specific actions
if ( $_ . KeyboardDevice . Modifiers -eq "Ctrl" ) {
switch ( $_ . Key ) {
"F" { $sync . SearchBar . Focus () } # Focus on the search bar
"Q" { $this . Close () } # Close the application
2023-11-28 16:11:11 -06:00
}
}
}
$sync [ "Form" ]. Add_PreViewKeyDown ( $commonKeyEvents )
$sync [ "Form" ]. Add_MouseLeftButtonDown ({
2025-08-01 22:04:00 +05:30
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" , "Theme" , "FontScaling" )
2023-11-28 16:11:11 -06:00
$sync [ "Form" ]. DragMove ()
})
2023-12-19 13:55:55 -06:00
$sync [ "Form" ]. Add_MouseDoubleClick ({
2025-04-14 20:55:52 +03:00
if ( $_ . OriginalSource . Name -eq "NavDockPanel" -or
$_ . OriginalSource . Name -eq "GridBesideNavDockPanel" ) {
2024-09-20 09:03:18 -05:00
if ( $sync [ "Form" ]. WindowState -eq [ Windows.WindowState ]:: Normal ) {
2024-09-20 15:32:41 +02:00
$sync [ "Form" ]. WindowState = [ Windows.WindowState ]:: Maximized
}
else {
$sync [ "Form" ]. WindowState = [ Windows.WindowState ]:: Normal
}
2023-12-19 13:55:55 -06:00
}
})
2024-01-15 11:32:19 -06:00
$sync [ "Form" ]. Add_Deactivated ({
2025-08-01 22:04:00 +05:30
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" , "Theme" , "FontScaling" )
2024-01-15 11:32:19 -06:00
})
$sync [ "Form" ]. Add_ContentRendered ({
2024-01-12 00:34:41 -06:00
# Load the Windows Forms assembly
Add-Type -AssemblyName System . Windows . Forms
$primaryScreen = [ System.Windows.Forms.Screen ]:: PrimaryScreen
# Check if the primary screen is found
if ( $primaryScreen ) {
# Extract screen width and height for the primary monitor
$screenWidth = $primaryScreen . Bounds . Width
$screenHeight = $primaryScreen . Bounds . Height
# Compare with the primary monitor size
2025-05-05 17:06:45 +02:00
if ( $sync . Form . ActualWidth -gt $screenWidth -or $sync . Form . ActualHeight -gt $screenHeight ) {
$sync . Form . Left = 0
$sync . Form . Top = 0
$sync . Form . Width = $screenWidth
$sync . Form . Height = $screenHeight
2024-01-12 00:34:41 -06:00
}
}
2024-02-02 16:22:08 -06:00
2026-03-04 12:21:18 -06:00
if ( $PARAM_OFFLINE ) {
# Show offline banner
$sync . WPFOfflineBanner . Visibility = [ System.Windows.Visibility ]:: Visible
2025-10-06 09:57:32 -05:00
2025-09-18 10:26:11 -05:00
# Disable the install tab
$sync . WPFTab1BT . IsEnabled = $false
$sync . WPFTab1BT . Opacity = 0.5
$sync . WPFTab1BT . ToolTip = "Internet connection required for installing applications"
# Disable install-related buttons
$sync . WPFInstall . IsEnabled = $false
$sync . WPFUninstall . IsEnabled = $false
$sync . WPFInstallUpgrade . IsEnabled = $false
$sync . WPFGetInstalled . IsEnabled = $false
# Show offline indicator
Write-Host "Offline mode detected - Install tab disabled" -ForegroundColor Yellow
# Optionally switch to a different tab if install tab was going to be default
Invoke-WPFTab "WPFTab2BT" # Switch to Tweaks tab instead
}
else {
# Online - ensure install tab is enabled
$sync . WPFTab1BT . IsEnabled = $true
$sync . WPFTab1BT . Opacity = 1.0
$sync . WPFTab1BT . ToolTip = $null
Invoke-WPFTab "WPFTab1BT" # Default to install tab
}
2026-06-08 18:02:35 +03:00
if ( -not $Config -and ( Test-Path " $winutildir \lastrun.json" )) {
$drifted = @ ( Get-Content " $winutildir \lastrun.json" | ConvertFrom-Json | Where-Object { $_ -notin ( Invoke-WinUtilCurrentSystem -CheckBox "tweaks" ) })
if ( $drifted . Count -gt 0 -and [ System.Windows.MessageBox ]:: Show ( " $( $drifted . Count ) tweak(s) were reverted since last run. Re-select them?" , "Winutil" , "YesNo" , "Question" ) -eq "Yes" ) {
Update-WinUtilSelections -flatJson $drifted
Reset-WPFCheckBoxes -doToggles $false
Invoke-WPFTab "WPFTab2BT"
2024-01-15 11:32:19 -06:00
}
}
2026-06-08 18:02:35 +03:00
$sync [ "Form" ]. Focus ()
2023-11-28 16:11:11 -06:00
})
2025-05-23 17:56:24 +02:00
# The SearchBarTimer is used to delay the search operation until the user has stopped typing for a short period
# This prevents the ui from stuttering when the user types quickly as it dosnt need to update the ui for every keystroke
$searchBarTimer = New-Object System . Windows . Threading . DispatcherTimer
$searchBarTimer . Interval = [ TimeSpan ]:: FromMilliseconds ( 300 )
$searchBarTimer . IsEnabled = $false
$searchBarTimer . add_Tick ({
$searchBarTimer . Stop ()
2025-03-01 20:50:12 +01:00
switch ( $sync . currentTab ) {
"Install" {
Find-AppsByNameOrDescription -SearchString $sync . SearchBar . Text
2024-01-12 00:34:41 -06:00
}
2025-05-05 20:45:51 +05:30
"Tweaks" {
Find-TweaksByNameOrDescription -SearchString $sync . SearchBar . Text
}
2024-01-12 00:34:41 -06:00
}
2023-11-28 16:11:11 -06:00
})
2025-05-23 17:56:24 +02:00
$sync [ "SearchBar" ]. Add_TextChanged ({
if ( $sync . SearchBar . Text -ne "" ) {
$sync . SearchBarClearButton . Visibility = "Visible"
} else {
$sync . SearchBarClearButton . Visibility = "Collapsed"
}
if ( $searchBarTimer . IsEnabled ) {
$searchBarTimer . Stop ()
}
$searchBarTimer . Start ()
})
2023-11-28 16:11:11 -06:00
2024-08-30 19:46:00 +02:00
$sync [ "Form" ]. Add_Loaded ({
param ( $e )
2025-03-01 20:50:12 +01:00
$sync . Form . MinWidth = "1000"
2024-08-30 19:46:00 +02:00
$sync [ "Form" ]. MaxWidth = [ Double ]:: PositiveInfinity
$sync [ "Form" ]. MaxHeight = [ Double ]:: PositiveInfinity
})
2024-09-10 03:19:34 +02:00
$NavLogoPanel = $sync [ "Form" ]. FindName ( "NavLogoPanel" )
$NavLogoPanel . Children . Add (( Invoke-WinUtilAssets -Type "logo" -Size 25 )) | Out-Null
2024-07-25 23:19:45 +02:00
2025-12-11 21:34:03 +02:00
if ( Test-Path " $winutildir \logo.ico" ) {
$sync [ "logorender" ] = " $winutildir \logo.ico"
2024-09-10 03:19:34 +02:00
} else {
$sync [ "logorender" ] = ( Invoke-WinUtilAssets -Type "Logo" -Size 90 -Render )
2024-07-25 23:19:45 +02:00
}
2024-09-10 03:19:34 +02:00
$sync [ "checkmarkrender" ] = ( Invoke-WinUtilAssets -Type "checkmark" -Size 512 -Render )
$sync [ "warningrender" ] = ( Invoke-WinUtilAssets -Type "warning" -Size 512 -Render )
2024-07-25 23:19:45 +02:00
Set-WinUtilTaskbaritem -overlay "logo"
$sync [ "Form" ]. Add_Activated ({
Set-WinUtilTaskbaritem -overlay "logo"
})
2024-12-06 06:22:33 +03:00
2024-09-20 15:34:10 +02:00
$sync [ "ThemeButton" ]. Add_Click ({
2025-08-01 22:04:00 +05:30
Invoke-WPFPopup -PopupActionTable @ { "Settings" = "Hide" ; "Theme" = "Toggle" ; "FontScaling" = "Hide" }
2024-09-20 15:34:10 +02:00
})
$sync [ "AutoThemeMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Theme" )
2024-09-20 15:34:10 +02:00
Invoke-WinutilThemeChange -theme "Auto"
2024-12-06 06:22:33 +03:00
})
2024-09-20 15:34:10 +02:00
$sync [ "DarkThemeMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Theme" )
2024-09-20 15:34:10 +02:00
Invoke-WinutilThemeChange -theme "Dark"
2024-12-06 06:22:33 +03:00
})
2024-09-20 15:34:10 +02:00
$sync [ "LightThemeMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Theme" )
2024-09-20 15:34:10 +02:00
Invoke-WinutilThemeChange -theme "Light"
2024-12-06 06:22:33 +03:00
})
2024-09-20 15:34:10 +02:00
2024-01-15 11:32:19 -06:00
$sync [ "SettingsButton" ]. Add_Click ({
2025-08-01 22:04:00 +05:30
Invoke-WPFPopup -PopupActionTable @ { "Settings" = "Toggle" ; "Theme" = "Hide" ; "FontScaling" = "Hide" }
2024-01-15 11:32:19 -06:00
})
$sync [ "ImportMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" )
Invoke-WPFImpex -type "import"
2024-01-15 11:32:19 -06:00
})
$sync [ "ExportMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" )
2024-01-15 11:32:19 -06:00
Invoke-WPFImpex -type "export"
})
$sync [ "AboutMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" )
2024-01-15 11:32:19 -06:00
$authorInfo = @"
2026-03-06 14:29:20 +00:00
Author : <a href="https://github.com/ChrisTitusTech">@ChrisTitusTech</a>
2025-05-23 11:20:23 -05:00
UI : <a href="https://github.com/MyDrift-user">@MyDrift-user</a>, <a href="https://github.com/Marterich">@Marterich</a>
Runspace : <a href="https://github.com/DeveloperDurp">@DeveloperDurp</a>, <a href="https://github.com/Marterich">@Marterich</a>
2024-06-25 20:54:18 +02:00
GitHub : <a href="https://github.com/ChrisTitusTech/winutil">ChrisTitusTech/winutil</a>
Version : <a href="https://github.com/ChrisTitusTech/winutil/releases/tag/ $( $sync . version ) "> $( $sync . version ) </a>
2024-02-02 16:22:08 -06:00
"@
2024-12-06 06:22:33 +03:00
Show-CustomDialog -Title "About" -Message $authorInfo
2024-01-15 11:32:19 -06:00
})
2026-03-06 14:29:20 +00:00
$sync [ "DocumentationMenuItem" ]. Add_Click ({
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" )
Start-Process "https://winutil.christitus.com/"
})
2024-07-14 18:50:40 -05:00
$sync [ "SponsorMenuItem" ]. Add_Click ({
2024-12-06 06:22:33 +03:00
Invoke-WPFPopup -Action "Hide" -Popups @ ( "Settings" )
2024-07-14 18:50:40 -05:00
$authorInfo = @"
<a href="https://github.com/sponsors/ChrisTitusTech">Current sponsors for ChrisTitusTech:</a>
"@
$authorInfo += " `n "
try {
$sponsors = Invoke-WinUtilSponsors
2024-12-06 06:22:33 +03:00
foreach ( $sponsor in $sponsors ) {
$authorInfo += "<a href= `" https://github.com/sponsors/ChrisTitusTech `" > $sponsor </a> `n "
}
2024-08-06 23:35:17 +03:00
} catch {
2024-07-14 18:50:40 -05:00
$authorInfo += "An error occurred while fetching or processing the sponsors: $_ `n "
}
2024-12-06 06:22:33 +03:00
Show-CustomDialog -Title "Sponsors" -Message $authorInfo -EnableScroll $true
2024-07-14 18:50:40 -05:00
})
2024-09-20 15:34:10 +02:00
2025-08-01 22:04:00 +05:30
# Font Scaling Event Handlers
$sync [ "FontScalingButton" ]. Add_Click ({
Invoke-WPFPopup -PopupActionTable @ { "Settings" = "Hide" ; "Theme" = "Hide" ; "FontScaling" = "Toggle" }
})
$sync [ "FontScalingSlider" ]. Add_ValueChanged ({
param ( $slider )
$percentage = [ math ]:: Round ( $slider . Value * 100 )
$sync . FontScalingValue . Text = " $percentage %"
})
$sync [ "FontScalingResetButton" ]. Add_Click ({
$sync . FontScalingSlider . Value = 1.0
$sync . FontScalingValue . Text = "100%"
})
$sync [ "FontScalingApplyButton" ]. Add_Click ({
$scaleFactor = $sync . FontScalingSlider . Value
Invoke-WinUtilFontScaling -ScaleFactor $scaleFactor
Invoke-WPFPopup -Action "Hide" -Popups @ ( "FontScaling" )
})
2026-02-24 15:28:49 -06:00
# ── Win11ISO Tab button handlers ──────────────────────────────────────────────
2026-03-03 00:19:37 -06:00
$sync [ "WPFTab5BT" ]. Add_Click ({
$sync [ "Form" ]. Dispatcher . BeginInvoke ([ System.Windows.Threading.DispatcherPriority ]:: Background , [ action ]{ Invoke-WinUtilISOCheckExistingWork }) | Out-Null
})
2026-02-24 15:28:49 -06:00
$sync [ "WPFWin11ISOBrowseButton" ]. Add_Click ({
Invoke-WinUtilISOBrowse
})
$sync [ "WPFWin11ISODownloadLink" ]. Add_Click ({
Start-Process "https://www.microsoft.com/software-download/windows11"
})
$sync [ "WPFWin11ISOMountButton" ]. Add_Click ({
Invoke-WinUtilISOMountAndVerify
})
$sync [ "WPFWin11ISOModifyButton" ]. Add_Click ({
Invoke-WinUtilISOModify
})
$sync [ "WPFWin11ISOChooseISOButton" ]. Add_Click ({
$sync [ "WPFWin11ISOOptionUSB" ]. Visibility = "Collapsed"
Invoke-WinUtilISOExport
})
$sync [ "WPFWin11ISOChooseUSBButton" ]. Add_Click ({
$sync [ "WPFWin11ISOOptionUSB" ]. Visibility = "Visible"
Invoke-WinUtilISORefreshUSBDrives
})
$sync [ "WPFWin11ISORefreshUSBButton" ]. Add_Click ({
Invoke-WinUtilISORefreshUSBDrives
})
$sync [ "WPFWin11ISOWriteUSBButton" ]. Add_Click ({
Invoke-WinUtilISOWriteUSB
})
$sync [ "WPFWin11ISOCleanResetButton" ]. Add_Click ({
Invoke-WinUtilISOCleanAndReset
})
# ──────────────────────────────────────────────────────────────────────────────
2023-11-28 16:11:11 -06:00
$sync [ "Form" ]. ShowDialog () | out-null
2024-03-21 16:23:24 -07:00
Stop-Transcript