- add overlay presets
- rework image saving & converting
- removed popup after uninstalling applications
This commit is contained in:
MyDrift 2024-07-14 21:30:11 +02:00
parent 0ff05828e1
commit c2c2e5ea71
12 changed files with 315 additions and 134 deletions

View File

@ -4,20 +4,32 @@ function Set-WinUtilTaskbaritem {
.SYNOPSIS .SYNOPSIS
Modifies the Taskbaritem of the WPF Form Modifies the Taskbaritem of the WPF Form
.PARAMETER state & value .PARAMETER value
Value can be between 0 and 1, 0 being no progress done yet and 1 being fully completed Value can be between 0 and 1, 0 being no progress done yet and 1 being fully completed
State can be 'None' > No progress, 'Indeterminate' > Without value, 'Normal' > when using value, 'Error' > Red (when using value), 'Paused' > Yellow (when using value) Value does not affect item without setting the state to 'Normal', 'Error' or 'Paused'
Set-WinUtilTaskbaritem -value 0.5
.PARAMETER state
State can be 'None' > No progress, 'Indeterminate' > inf. loading gray, 'Normal' > Gray, 'Error' > Red, 'Paused' > Yellow
no value needed:
- Set-WinUtilTaskbaritem -state "None"
- Set-WinUtilTaskbaritem -state "Indeterminate"
value needed:
- Set-WinUtilTaskbaritem -state "Error"
- Set-WinUtilTaskbaritem -state "Normal"
- Set-WinUtilTaskbaritem -state "Paused"
.PARAMETER overlay .PARAMETER overlay
Overlay icon to display on the taskbar item Overlay icon to display on the taskbar item, there are the presets 'logo' and 'checkmark' or you can specify a path/link to an image file.
CTT logo preset:
- Set-WinUtilTaskbaritem -overlay "logo"
Checkmark preset:
- Set-WinUtilTaskbaritem -overlay "checkmark"
Custom icon:
- Set-WinUtilTaskbaritem -overlay "C:\path\to\icon.png"
.EXAMPLE .PARAMETER description
Set-WinUtilTaskbaritem -value 0.5 -state "Normal" Description to display on the taskbar item preview
Set-WinUtilTaskbaritem -state "Error"
Set-WinUtilTaskbaritem -state "Indeterminate"
Set-WinUtilTaskbaritem -description "This is a description" Set-WinUtilTaskbaritem -description "This is a description"
Set-WinUtilTaskbaritem -overlay "C:\path\to\icon.png"
#> #>
param ( param (
[double]$value, [double]$value,
@ -32,37 +44,29 @@ function Set-WinUtilTaskbaritem {
if ($state) { if ($state) {
switch ($state) { switch ($state) {
'None' { $sync["Form"].taskbarItemInfo.ProgressState = "None" }
'Indeterminate' { $sync["Form"].taskbarItemInfo.ProgressState = "Indeterminate" } 'Indeterminate' { $sync["Form"].taskbarItemInfo.ProgressState = "Indeterminate" }
'Normal' { $sync["Form"].taskbarItemInfo.ProgressState = "Normal" } 'Normal' { $sync["Form"].taskbarItemInfo.ProgressState = "Normal" }
'Error' { $sync["Form"].taskbarItemInfo.ProgressState = "Error" } 'Error' { $sync["Form"].taskbarItemInfo.ProgressState = "Error" }
'Paused' { $sync["Form"].taskbarItemInfo.ProgressState = "Paused" } 'Paused' { $sync["Form"].taskbarItemInfo.ProgressState = "Paused" }
default { $sync["Form"].taskbarItemInfo.ProgressState = "None" } default { write-host "Invalid state" }
} }
} }
if ($overlay -and (Test-Path $overlay)) { if ($overlay) {
# Read the image file as a byte array switch ($overlay) {
$imageBytes = [System.IO.File]::ReadAllBytes($overlay) 'logo' {
$sync["Form"].taskbarItemInfo.Overlay = (ConvertTo-Bitmap -image "$env:LOCALAPPDATA\winutil\cttlogo.png")
# Convert the byte array to a Base64 string }
[System.Convert]::ToBase64String($imageBytes) 'checkmark' {
$sync["Form"].taskbarItemInfo.Overlay = (ConvertTo-Bitmap -image "$env:LOCALAPPDATA\winutil\cttcheckmark.png")
# Load the image file as a bitmap }
$bitmap = [System.Drawing.Bitmap]::new($overlay) default {
if (Test-Path $overlay) {
# Create a streaming image by streaming the bitmap to a memory stream $sync["Form"].taskbarItemInfo.Overlay = (ConvertTo-Bitmap -image $overlay)
$memoryStream = [System.IO.MemoryStream]::new() }
$bitmap.Save($memoryStream, [System.Drawing.Imaging.ImageFormat]::Png) }
$memoryStream.Position = 0 }
# Create a bitmap image from the memory stream
$bitmapImage = [System.Windows.Media.Imaging.BitmapImage]::new()
$bitmapImage.BeginInit()
$bitmapImage.StreamSource = $memoryStream
$bitmapImage.EndInit()
$bitmapImage.Freeze()
$sync["Form"].taskbarItemInfo.Overlay = $bitmapImage
} }
if ($description) { if ($description) {

View File

@ -0,0 +1,31 @@
function ConvertTo-Bitmap {
<#
.SYNOPSIS
Converts an image file to a Bitmap object
.PARAMETER image
The path to the image file to convert
.EXAMPLE
ConvertTo-Bitmap -image "C:\path\to\image.png"
#>
param (
$image
)
# Read the image file as a byte array
$imageBytes = [System.IO.File]::ReadAllBytes($image)
# Convert the byte array to a Base64 string
$base64String = [System.Convert]::ToBase64String($imageBytes)
# Create a streaming image by streaming the base64 string to a bitmap streamsource
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($base64String)
$bitmap.EndInit()
$bitmap.Freeze()
# Return the bitmap object
return $bitmap
}

View File

@ -18,15 +18,15 @@ function Invoke-WPFFeatureInstall {
param($Features, $DebugPreference) 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 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
} }
Invoke-WinUtilFeatureInstall $Features Invoke-WinUtilFeatureInstall $Features
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "$env:TEMP\cttcheck.png" }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Write-Host "===================================" Write-Host "==================================="
Write-Host "--- Features are Installed ---" Write-Host "--- Features are Installed ---"

View File

@ -89,7 +89,7 @@ function Invoke-WPFGetIso {
return return
} }
Set-WinUtilTaskbaritem -state "Indeterminate" Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
# Detect the file size of the ISO and compare it with the free space of the system drive # Detect the file size of the ISO and compare it with the free space of the system drive
$isoSize = (Get-Item -Path $filePath).Length $isoSize = (Get-Item -Path $filePath).Length
@ -245,7 +245,7 @@ function Invoke-WPFGetIso {
$sync.BusyMessage.Visibility="Hidden" $sync.BusyMessage.Visibility="Hidden"
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
Set-WinUtilTaskbaritem -state "None" Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
} }

View File

@ -24,9 +24,9 @@ function Invoke-WPFInstall {
Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $DebugPreference) param($PackagesToInstall, $DebugPreference)
if ($PackagesToInstall.count -eq 1){ if ($PackagesToInstall.count -eq 1){
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
} }
$packagesWinget, $packagesChoco = { $packagesWinget, $packagesChoco = {
$packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new() $packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new()
@ -58,7 +58,7 @@ 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 "$env:TEMP\cttcheck.png" }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
} }
Catch { Catch {
Write-Host "===========================================" Write-Host "==========================================="
@ -66,7 +66,6 @@ function Invoke-WPFInstall {
Write-Host "===========================================" Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
} }
Start-Sleep -Seconds 5
$sync.ProcessRunning = $False $sync.ProcessRunning = $False
} }
} }

View File

@ -40,10 +40,11 @@ public class PowerManagement {
if ($SaveDialog.FileName -eq "") { if ($SaveDialog.FileName -eq "") {
Write-Host "No file name for the target image was specified" Write-Host "No file name for the target image was specified"
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
Set-WinUtilTaskbaritem -state "Indeterminate" Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
Write-Host "Target ISO location: $($SaveDialog.FileName)" Write-Host "Target ISO location: $($SaveDialog.FileName)"
@ -474,7 +475,7 @@ public class PowerManagement {
#$msg = "Done. ISO image is located here: $env:temp\microwin.iso" #$msg = "Done. ISO image is located here: $env:temp\microwin.iso"
$msg = "Done. ISO image is located here: $($SaveDialog.FileName)" $msg = "Done. ISO image is located here: $($SaveDialog.FileName)"
Write-Host $msg Write-Host $msg
Set-WinUtilTaskbaritem -state "None" Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information) [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information)
} else { } else {
Write-Host "ISO creation failed. The "$($mountDir)" directory has not been removed." Write-Host "ISO creation failed. The "$($mountDir)" directory has not been removed."
@ -487,6 +488,5 @@ public class PowerManagement {
# Allow the machine to sleep again (optional) # Allow the machine to sleep again (optional)
[PowerManagement]::SetThreadExecutionState(0) [PowerManagement]::SetThreadExecutionState(0)
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
Set-WinUtilTaskbaritem -state "None"
} }
} }

View File

@ -27,12 +27,6 @@ function Invoke-WPFShortcut {
$ArgumentsToSourceExe = "$powershell '$IRM'" $ArgumentsToSourceExe = "$powershell '$IRM'"
$DestinationName = "WinUtil.lnk" $DestinationName = "WinUtil.lnk"
Invoke-WebRequest -Uri "https://christitus.com/images/logo-full.png" -OutFile "$env:TEMP\cttlogo.png"
if (Test-Path -Path "$env:TEMP\cttlogo.png") {
$iconPath = "$env:LOCALAPPDATA\winutil\cttlogo.ico"
ConvertTo-Icon -bitmapPath "$env:TEMP\cttlogo.png" -iconPath $iconPath
}
} }
} }
@ -54,8 +48,8 @@ function Invoke-WPFShortcut {
$Shortcut = $WshShell.CreateShortcut($FileBrowser.FileName) $Shortcut = $WshShell.CreateShortcut($FileBrowser.FileName)
$Shortcut.TargetPath = $SourceExe $Shortcut.TargetPath = $SourceExe
$Shortcut.Arguments = $ArgumentsToSourceExe $Shortcut.Arguments = $ArgumentsToSourceExe
if ($iconPath -ne $null) { if (Test-Path -Path $ctticologo) {
$shortcut.IconLocation = $iconPath $shortcut.IconLocation = $ctticologo
} }
# Save the Shortcut to disk # Save the Shortcut to disk

View File

@ -33,9 +33,9 @@ function Invoke-WPFUnInstall {
Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $DebugPreference) param($PackagesToInstall, $DebugPreference)
if ($PackagesToInstall.count -eq 1){ if ($PackagesToInstall.count -eq 1){
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
} }
$packagesWinget, $packagesChoco = { $packagesWinget, $packagesChoco = {
$packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new() $packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new()
@ -67,7 +67,7 @@ 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 "$env:TEMP\cttcheck.png" }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
} }
Catch { Catch {
Write-Host "===========================================" Write-Host "==========================================="
@ -77,9 +77,5 @@ function Invoke-WPFUnInstall {
} }
$sync.ProcessRunning = $False $sync.ProcessRunning = $False
$ButtonType = [System.Windows.MessageBoxButton]::OK
$MessageboxTitle = "Uninstalls are Finished "
$Messageboxbody = ("Done")
$MessageIcon = [System.Windows.MessageBoxImage]::Information
} }
} }

View File

@ -31,9 +31,9 @@ function Invoke-WPFtweaksbutton {
$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 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
} }
$cnt = 0 $cnt = 0
# Execute other selected tweaks # Execute other selected tweaks
@ -45,7 +45,7 @@ function Invoke-WPFtweaksbutton {
} }
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "$env:TEMP\cttcheck.png" }) $sync.form.Dispatcher.Invoke([action]{ 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

@ -25,9 +25,9 @@ function Invoke-WPFundoall {
$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 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
} else { } else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 }) $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
} }
$cnt = 0 $cnt = 0
@ -38,7 +38,7 @@ function Invoke-WPFundoall {
} }
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "$env:TEMP\cttcheck.png" }) $sync.form.Dispatcher.Invoke([action]{ 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

@ -154,19 +154,6 @@ Invoke-WPFRunspace -ScriptBlock {
# Print the logo # Print the logo
Invoke-WPFFormVariables Invoke-WPFFormVariables
# download the logo
$logoUrl = "https://christitus.com/images/logo-full.png"
# Download the image
$logoPath = "$env:TEMP\cttlogo.png"
Invoke-WebRequest -Uri $logoUrl -OutFile $logoPath
# download the check
$CheckUrl = "https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/docs/assets/check.png"
# Download the image
$CheckPath = "$env:TEMP\cttcheck.png"
Invoke-WebRequest -Uri $CheckUrl -OutFile $CheckPath
# Progress bar in taskbaritem > Set-WinUtilProgressbar # Progress bar in taskbaritem > Set-WinUtilProgressbar
$sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo $sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo
Set-WinUtilTaskbaritem -state "None" Set-WinUtilTaskbaritem -state "None"
@ -305,9 +292,6 @@ Add-Type @"
} }
} }
# Set the overlay icon for the taskbar
Set-WinUtilTaskbaritem -overlay $logoPath
$rect = New-Object RECT $rect = New-Object RECT
[Window]::GetWindowRect($windowHandle, [ref]$rect) [Window]::GetWindowRect($windowHandle, [ref]$rect)
$width = $rect.Right - $rect.Left $width = $rect.Right - $rect.Left
@ -446,8 +430,25 @@ $sync["SearchBar"].Add_TextChanged({
$label.Visibility = "Collapsed"} $label.Visibility = "Collapsed"}
}) })
$cttpnglogo = "$env:LOCALAPPDATA\winutil\cttlogo.png"
$ctticologo = "$env:LOCALAPPDATA\winutil\cttlogo.ico"
if (-NOT (Test-Path -Path $cttpnglogo) -or -NOT (Test-Path -Path $ctticologo)) {
Invoke-WebRequest -Uri "https://christitus.com/images/logo-full.png" -OutFile $cttpnglogo
}
$cttpngcheckmark = "$env:LOCALAPPDATA\winutil\cttcheckmark.png"
$ctticocheckmark = "$env:LOCALAPPDATA\winutil\cttcheckmark.ico"
if (-NOT (Test-Path -Path $cttpngcheckmark) -or -NOT (Test-Path -Path $ctticocheckmark)) {
Invoke-WebRequest -Uri "https://christitus.com/images/checkmark.png" -OutFile $cttpngcheckmark
}
ConvertTo-Icon -bitmapPath $cttpnglogo -iconPath $ctticologo
Set-WinUtilTaskbaritem -overlay "logo" | Out-Null
$sync["Form"].icon = $cttpnglogo
$sync["Form"].Add_Activated({ $sync["Form"].Add_Activated({
Set-WinUtilTaskbaritem -overlay $logoPath -state "None" Set-WinUtilTaskbaritem -overlay "logo"
}) })
# Define event handler for button click # Define event handler for button click

View File

@ -8,7 +8,7 @@
Author : Chris Titus @christitustech Author : Chris Titus @christitustech
Runspace Author: @DeveloperDurp Runspace Author: @DeveloperDurp
GitHub : https://github.com/ChrisTitusTech GitHub : https://github.com/ChrisTitusTech
Version : 24.07.13 Version : 24.07.14
#> #>
param ( param (
[switch]$Debug, [switch]$Debug,
@ -45,7 +45,7 @@ Add-Type -AssemblyName System.Windows.Forms
# Variable to sync between runspaces # Variable to sync between runspaces
$sync = [Hashtable]::Synchronized(@{}) $sync = [Hashtable]::Synchronized(@{})
$sync.PSScriptRoot = $PSScriptRoot $sync.PSScriptRoot = $PSScriptRoot
$sync.version = "24.07.13" $sync.version = "24.07.14"
$sync.configs = @{} $sync.configs = @{}
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
@ -62,6 +62,27 @@ If (([Security.Principal.WindowsIdentity]::GetCurrent()).Owner.Value -ne "S-1-5-
# Set PowerShell window title # Set PowerShell window title
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)"
clear-host clear-host
function ConvertTo-Bitmap {
param (
$image
)
# Read the image file as a byte array
$imageBytes = [System.IO.File]::ReadAllBytes($image)
# Convert the byte array to a Base64 string
$base64String = [System.Convert]::ToBase64String($imageBytes)
# Create a streaming image by streaming the base64 string to a bitmap streamsource
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($base64String)
$bitmap.EndInit()
$bitmap.Freeze()
# Return the bitmap object
return $bitmap
}
function ConvertTo-Icon { function ConvertTo-Icon {
<# <#
@ -922,12 +943,18 @@ function Install-WinUtilProgramChoco {
} }
if(($chocoInstallStatus -eq 0) -AND ($tryUpgrade -eq $false)){ if(($chocoInstallStatus -eq 0) -AND ($tryUpgrade -eq $false)){
Write-Host "$($Program.choco) installed successfully using Chocolatey." Write-Host "$($Program.choco) installed successfully using Chocolatey."
$X++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value ($x/$count) })
continue continue
} else { } else {
Write-Host "Failed to install $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $installOutputFilePath)." Write-Host "Failed to install $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $installOutputFilePath)."
$X++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) })
} }
} catch { } catch {
Write-Host "Failed to install $($Program.choco) due to an error: $_" Write-Host "Failed to install $($Program.choco) due to an error: $_"
$X++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) })
} }
} }
@ -939,15 +966,20 @@ function Install-WinUtilProgramChoco {
$chocoUninstallStatus = $(Start-Process -FilePath "choco" -ArgumentList "uninstall $($Program.choco) -y" -Wait -PassThru).ExitCode $chocoUninstallStatus = $(Start-Process -FilePath "choco" -ArgumentList "uninstall $($Program.choco) -y" -Wait -PassThru).ExitCode
if($chocoUninstallStatus -eq 0){ if($chocoUninstallStatus -eq 0){
Write-Host "$($Program.choco) uninstalled successfully using Chocolatey." Write-Host "$($Program.choco) uninstalled successfully using Chocolatey."
$x++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value ($x/$count) })
continue continue
} else { } else {
Write-Host "Failed to uninstall $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $uninstallOutputFilePath)." Write-Host "Failed to uninstall $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $uninstallOutputFilePath)."
$x++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) })
} }
} catch { } catch {
Write-Host "Failed to uninstall $($Program.choco) due to an error: $_" Write-Host "Failed to uninstall $($Program.choco) due to an error: $_"
$x++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) })
} }
} }
$x++
} }
Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed
@ -1002,20 +1034,24 @@ Function Install-WinUtilProgramWinget {
$status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru -NoNewWindow).ExitCode $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru -NoNewWindow).ExitCode
if($status -eq 0) { if($status -eq 0) {
Write-Host "$($Program.winget) installed successfully." Write-Host "$($Program.winget) installed successfully."
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
continue continue
} }
if ($status -eq -1978335189) { if ($status -eq -1978335189) {
Write-Host "$($Program.winget) No applicable update found" Write-Host "$($Program.winget) No applicable update found"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
continue continue
} }
Write-Host "Attempt with User scope" Write-Host "Attempt with User scope"
$status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru -NoNewWindow).ExitCode $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru -NoNewWindow).ExitCode
if($status -eq 0) { if($status -eq 0) {
Write-Host "$($Program.winget) installed successfully with User scope." Write-Host "$($Program.winget) installed successfully with User scope."
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
continue continue
} }
if ($status -eq -1978335189) { if ($status -eq -1978335189) {
Write-Host "$($Program.winget) No applicable update found" Write-Host "$($Program.winget) No applicable update found"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
continue continue
} }
Write-Host "Attempt with User prompt" Write-Host "Attempt with User prompt"
@ -1030,15 +1066,18 @@ Function Install-WinUtilProgramWinget {
} }
if($status -eq 0) { if($status -eq 0) {
Write-Host "$($Program.winget) installed successfully with User prompt." Write-Host "$($Program.winget) installed successfully with User prompt."
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
continue continue
} }
if ($status -eq -1978335189) { if ($status -eq -1978335189) {
Write-Host "$($Program.winget) No applicable update found" Write-Host "$($Program.winget) No applicable update found"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
continue continue
} }
} catch { } catch {
Write-Host "Failed to install $($Program.winget). With winget" Write-Host "Failed to install $($Program.winget). With winget"
$failedPackages += $Program $failedPackages += $Program
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($i/$count) })
} }
} }
elseif($manage -eq "Uninstalling") { elseif($manage -eq "Uninstalling") {
@ -1054,7 +1093,9 @@ Function Install-WinUtilProgramWinget {
} catch { } catch {
Write-Host "Failed to uninstall $($Program.winget) due to an error: $_" Write-Host "Failed to uninstall $($Program.winget) due to an error: $_"
$failedPackages += $Program $failedPackages += $Program
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
} }
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$count) })
} }
else { else {
throw "[Install-WinUtilProgramWinget] Invalid Value for Parameter 'manage', Provided Value is: $manage" throw "[Install-WinUtilProgramWinget] Invalid Value for Parameter 'manage', Provided Value is: $manage"
@ -1084,6 +1125,7 @@ function Install-WinUtilWinget {
Write-Host "`nWinget is not Installed. Continuing with install.`r" -ForegroundColor Red Write-Host "`nWinget is not Installed. Continuing with install.`r" -ForegroundColor Red
} }
# Gets the computer's information # Gets the computer's information
if ($null -eq $sync.ComputerInfo){ if ($null -eq $sync.ComputerInfo){
$ComputerInfo = Get-ComputerInfo -ErrorAction Stop $ComputerInfo = Get-ComputerInfo -ErrorAction Stop
@ -1128,6 +1170,7 @@ function Install-WinUtilWinget {
throw [WingetFailedInstall]::new('Failed to install!') throw [WingetFailedInstall]::new('Failed to install!')
} }
} }
} }
function Test-CompatibleImage() { function Test-CompatibleImage() {
<# <#
@ -1967,6 +2010,8 @@ function Invoke-WinUtilFeatureInstall {
$CheckBox $CheckBox
) )
$x = 0
$CheckBox | ForEach-Object { $CheckBox | ForEach-Object {
if($sync.configs.feature.$psitem.feature){ if($sync.configs.feature.$psitem.feature){
Foreach( $feature in $sync.configs.feature.$psitem.feature ){ Foreach( $feature in $sync.configs.feature.$psitem.feature ){
@ -1977,9 +2022,11 @@ function Invoke-WinUtilFeatureInstall {
Catch{ Catch{
if ($psitem.Exception.Message -like "*requires elevation*"){ if ($psitem.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" })
} }
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 $psitem.Exception.StackTrace
} }
@ -1997,15 +2044,19 @@ function Invoke-WinUtilFeatureInstall {
Catch{ Catch{
if ($psitem.Exception.Message -like "*requires elevation*"){ if ($psitem.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" })
} }
else{ else{
$sync.form.Dispatcher.Invoke([action]{ 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 $psitem.Exception.StackTrace
} }
} }
} }
} }
$X++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) })
} }
} }
function Invoke-WinUtilGPU { function Invoke-WinUtilGPU {
@ -2749,6 +2800,69 @@ Function Set-WinUtilService {
} }
} }
function Set-WinUtilTaskbaritem {
<#
.SYNOPSIS
Modifies the Taskbaritem of the WPF Form
.PARAMETER state & value
Value can be between 0 and 1, 0 being no progress done yet and 1 being fully completed
State can be 'None' > No progress, 'Indeterminate' > Without value, 'Normal' > when using value, 'Error' > Red (when using value), 'Paused' > Yellow (when using value)
.PARAMETER overlay
Overlay icon to display on the taskbar item
.EXAMPLE
Set-WinUtilTaskbaritem -value 0.5 -state "Normal"
Set-WinUtilTaskbaritem -state "Error"
Set-WinUtilTaskbaritem -state "Indeterminate"
Set-WinUtilTaskbaritem -description "This is a description"
Set-WinUtilTaskbaritem -overlay "C:\path\to\icon.png"
#>
param (
[double]$value,
$state,
[string]$overlay,
$description
)
if ($value) {
$sync["Form"].taskbarItemInfo.ProgressValue = $value
}
if ($state) {
switch ($state) {
'None' { $sync["Form"].taskbarItemInfo.ProgressState = "None" }
'Indeterminate' { $sync["Form"].taskbarItemInfo.ProgressState = "Indeterminate" }
'Normal' { $sync["Form"].taskbarItemInfo.ProgressState = "Normal" }
'Error' { $sync["Form"].taskbarItemInfo.ProgressState = "Error" }
'Paused' { $sync["Form"].taskbarItemInfo.ProgressState = "Paused" }
default { write-host "Invalid state" }
}
}
if ($overlay) {
switch ($overlay) {
'logo' {
$sync["Form"].taskbarItemInfo.Overlay = (ConvertTo-Bitmap -image "$env:LOCALAPPDATA\winutil\cttlogo.png")
}
'checkmark' {
$sync["Form"].taskbarItemInfo.Overlay = (ConvertTo-Bitmap -image "$env:LOCALAPPDATA\winutil\cttcheckmark.png")
}
default {
if (Test-Path $overlay) {
$sync["Form"].taskbarItemInfo.Overlay = (ConvertTo-Bitmap -image $overlay)
}
}
}
}
if ($description) {
$sync["Form"].taskbarItemInfo.Description = $description
}
}
function Set-WinUtilUITheme { function Set-WinUtilUITheme {
<# <#
@ -3344,12 +3458,18 @@ function Invoke-WPFFeatureInstall {
Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock {
param($Features, $DebugPreference) param($Features, $DebugPreference)
$sync.ProcessRunning = $true $sync.ProcessRunning = $true
if ($Features.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" })
}
Invoke-WinUtilFeatureInstall $Features Invoke-WinUtilFeatureInstall $Features
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Write-Host "===================================" Write-Host "==================================="
Write-Host "--- Features are Installed ---" Write-Host "--- Features are Installed ---"
Write-Host "--- A Reboot may be required ---" Write-Host "--- A Reboot may be required ---"
@ -3753,6 +3873,7 @@ function Invoke-WPFGetInstalled {
param($checkbox, $DebugPreference) param($checkbox, $DebugPreference)
$sync.ProcessRunning = $true $sync.ProcessRunning = $true
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" })
if($checkbox -eq "winget"){ if($checkbox -eq "winget"){
Write-Host "Getting Installed Programs..." Write-Host "Getting Installed Programs..."
@ -3771,6 +3892,7 @@ function Invoke-WPFGetInstalled {
Write-Host "Done..." Write-Host "Done..."
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" })
} }
} }
function Invoke-WPFGetIso { function Invoke-WPFGetIso {
@ -3791,6 +3913,7 @@ function Invoke-WPFGetIso {
$sync.BusyText.Text="N Busy" $sync.BusyText.Text="N Busy"
Write-Host " _ __ __ _ " Write-Host " _ __ __ _ "
Write-Host " /\/\ (_) ___ _ __ ___ / / /\ \ \(_) _ __ " Write-Host " /\/\ (_) ___ _ __ ___ / / /\ \ \(_) _ __ "
Write-Host " / \ | | / __|| '__| / _ \ \ \/ \/ /| || '_ \ " Write-Host " / \ | | / __|| '__| / _ \ \ \/ \/ /| || '_ \ "
@ -3863,6 +3986,8 @@ function Invoke-WPFGetIso {
return return
} }
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
# Detect the file size of the ISO and compare it with the free space of the system drive # Detect the file size of the ISO and compare it with the free space of the system drive
$isoSize = (Get-Item -Path $filePath).Length $isoSize = (Get-Item -Path $filePath).Length
Write-Debug "Size of ISO file: $($isoSize) bytes" Write-Debug "Size of ISO file: $($isoSize) bytes"
@ -3879,6 +4004,7 @@ function Invoke-WPFGetIso {
{ {
# It's critical and we can't continue. Output an error # It's critical and we can't continue. Output an error
Write-Host "You don't have enough space for this operation. You need at least $([Math]::Round(($isoSize / ([Math]::Pow(1024, 2))) * 2, 2)) MB of free space to copy the ISO files to a temp directory and to be able to perform additional operations." Write-Host "You don't have enough space for this operation. You need at least $([Math]::Round(($isoSize / ([Math]::Pow(1024, 2))) * 2, 2)) MB of free space to copy the ISO files to a temp directory and to be able to perform additional operations."
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
else else
@ -3897,6 +4023,7 @@ function Invoke-WPFGetIso {
Write-Error "Failed to mount the image. Error: $($_.Exception.Message)" Write-Error "Failed to mount the image. Error: $($_.Exception.Message)"
Write-Error "This is NOT winutil's problem, your ISO might be corrupt, or there is a problem on the system" Write-Error "This is NOT winutil's problem, your ISO might be corrupt, or there is a problem on the system"
Write-Error "Please refer to this wiki for more details https://github.com/ChrisTitusTech/winutil/blob/main/wiki/Error-in-Winutil-MicroWin-during-ISO-mounting%2Cmd" Write-Error "Please refer to this wiki for more details https://github.com/ChrisTitusTech/winutil/blob/main/wiki/Error-in-Winutil-MicroWin-during-ISO-mounting%2Cmd"
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
# storing off values in hidden fields for further steps # storing off values in hidden fields for further steps
@ -3974,6 +4101,7 @@ function Invoke-WPFGetIso {
$msg = "Neither install.wim nor install.esd exist in the image, this could happen if you use unofficial Windows images. Please don't use shady images from the internet, use only official images. Here are instructions how to download ISO images if the Microsoft website is not showing the link to download and ISO. https://www.techrepublic.com/article/how-to-download-a-windows-10-iso-file-without-using-the-media-creation-tool/" $msg = "Neither install.wim nor install.esd exist in the image, this could happen if you use unofficial Windows images. Please don't use shady images from the internet, use only official images. Here are instructions how to download ISO images if the Microsoft website is not showing the link to download and ISO. https://www.techrepublic.com/article/how-to-download-a-windows-10-iso-file-without-using-the-media-creation-tool/"
Write-Host $msg Write-Host $msg
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
Set-WinUtilTaskbaritem -state "Error" -value 1
throw throw
} }
elseif ((-not (Test-Path -Path $wimFile -PathType Leaf)) -and (Test-Path -Path $wimFile.Replace(".wim", ".esd").Trim() -PathType Leaf)) elseif ((-not (Test-Path -Path $wimFile -PathType Leaf)) -and (Test-Path -Path $wimFile.Replace(".wim", ".esd").Trim() -PathType Leaf))
@ -4014,6 +4142,7 @@ function Invoke-WPFGetIso {
$sync.BusyMessage.Visibility="Hidden" $sync.BusyMessage.Visibility="Hidden"
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
} }
@ -4100,8 +4229,14 @@ function Invoke-WPFInstall {
return return
} }
Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $DebugPreference) param($PackagesToInstall, $DebugPreference)
if ($PackagesToInstall.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" })
}
$packagesWinget, $packagesChoco = { $packagesWinget, $packagesChoco = {
$packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new() $packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new()
$packagesChoco = [System.Collections.Generic.List`1[System.Object]]::new() $packagesChoco = [System.Collections.Generic.List`1[System.Object]]::new()
@ -4132,11 +4267,13 @@ 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" })
} }
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" })
} }
Start-Sleep -Seconds 5 Start-Sleep -Seconds 5
$sync.ProcessRunning = $False $sync.ProcessRunning = $False
@ -4159,6 +4296,8 @@ function Invoke-WPFInstallUpgrade {
return return
} }
# Set-WinUtilTaskbaritem -state "Indeterminate"
Update-WinUtilProgramWinget Update-WinUtilProgramWinget
Write-Host "===========================================" Write-Host "==========================================="
@ -4172,6 +4311,7 @@ function Invoke-WPFMicrowin {
Invoke MicroWin routines... Invoke MicroWin routines...
#> #>
if($sync.ProcessRunning) { if($sync.ProcessRunning) {
$msg = "GetIso process is currently running." $msg = "GetIso 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)
@ -4207,9 +4347,12 @@ public class PowerManagement {
if ($SaveDialog.FileName -eq "") { if ($SaveDialog.FileName -eq "") {
Write-Host "No file name for the target image was specified" Write-Host "No file name for the target image was specified"
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
Write-Host "Target ISO location: $($SaveDialog.FileName)" Write-Host "Target ISO location: $($SaveDialog.FileName)"
$index = $sync.MicrowinWindowsFlavors.SelectedValue.Split(":")[0].Trim() $index = $sync.MicrowinWindowsFlavors.SelectedValue.Split(":")[0].Trim()
@ -4242,6 +4385,7 @@ public class PowerManagement {
$msg = "The export process has failed and MicroWin processing cannot continue" $msg = "The export process has failed and MicroWin processing cannot continue"
Write-Host "Failed to export the image" Write-Host "Failed to export the image"
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error) [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
} }
@ -4255,6 +4399,7 @@ public class PowerManagement {
$dlg_msg = $msg + "`n`nIf you want more information, the version of the image selected is $($imgVersion)`n`nIf an image has been incorrectly marked as incompatible, report an issue to the developers." $dlg_msg = $msg + "`n`nIf you want more information, the version of the image selected is $($imgVersion)`n`nIf an image has been incorrectly marked as incompatible, report an issue to the developers."
Write-Host $msg Write-Host $msg
[System.Windows.MessageBox]::Show($dlg_msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Exclamation) [System.Windows.MessageBox]::Show($dlg_msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Exclamation)
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
@ -4263,6 +4408,7 @@ public class PowerManagement {
if (-not $mountDirExists -or -not $scratchDirExists) if (-not $mountDirExists -or -not $scratchDirExists)
{ {
Write-Error "Required directories '$mountDirExists' '$scratchDirExists' and do not exist." Write-Error "Required directories '$mountDirExists' '$scratchDirExists' and do not exist."
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
@ -4277,6 +4423,7 @@ public class PowerManagement {
else else
{ {
Write-Host "Could not mount image. Exiting..." Write-Host "Could not mount image. Exiting..."
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
@ -4533,6 +4680,7 @@ public class PowerManagement {
if (-not (Test-Path -Path "$mountDir\sources\install.wim")) if (-not (Test-Path -Path "$mountDir\sources\install.wim"))
{ {
Write-Error "Something went wrong and '$mountDir\sources\install.wim' doesn't exist. Please report this bug to the devs" Write-Error "Something went wrong and '$mountDir\sources\install.wim' doesn't exist. Please report this bug to the devs"
Set-WinUtilTaskbaritem -state "Error" -value 1
return return
} }
Write-Host "Windows image completed. Continuing with boot.wim." Write-Host "Windows image completed. Continuing with boot.wim."
@ -4634,6 +4782,7 @@ public class PowerManagement {
#$msg = "Done. ISO image is located here: $env:temp\microwin.iso" #$msg = "Done. ISO image is located here: $env:temp\microwin.iso"
$msg = "Done. ISO image is located here: $($SaveDialog.FileName)" $msg = "Done. ISO image is located here: $($SaveDialog.FileName)"
Write-Host $msg Write-Host $msg
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information) [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information)
} else { } else {
Write-Host "ISO creation failed. The "$($mountDir)" directory has not been removed." Write-Host "ISO creation failed. The "$($mountDir)" directory has not been removed."
@ -4879,12 +5028,6 @@ function Invoke-WPFShortcut {
$ArgumentsToSourceExe = "$powershell '$IRM'" $ArgumentsToSourceExe = "$powershell '$IRM'"
$DestinationName = "WinUtil.lnk" $DestinationName = "WinUtil.lnk"
Invoke-WebRequest -Uri "https://christitus.com/images/logo-full.png" -OutFile "$env:TEMP\cttlogo.png"
if (Test-Path -Path "$env:TEMP\cttlogo.png") {
$iconPath = "$env:LOCALAPPDATA\winutil\cttlogo.ico"
ConvertTo-Icon -bitmapPath "$env:TEMP\cttlogo.png" -iconPath $iconPath
}
} }
} }
@ -4906,8 +5049,8 @@ function Invoke-WPFShortcut {
$Shortcut = $WshShell.CreateShortcut($FileBrowser.FileName) $Shortcut = $WshShell.CreateShortcut($FileBrowser.FileName)
$Shortcut.TargetPath = $SourceExe $Shortcut.TargetPath = $SourceExe
$Shortcut.Arguments = $ArgumentsToSourceExe $Shortcut.Arguments = $ArgumentsToSourceExe
if ($iconPath -ne $null) { if (Test-Path -Path $ctticologo) {
$shortcut.IconLocation = $iconPath $shortcut.IconLocation = $ctticologo
} }
# Save the Shortcut to disk # Save the Shortcut to disk
@ -5065,15 +5208,22 @@ function Invoke-WPFtweaksbutton {
$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" })
}
$cnt = 0 $cnt = 0
# Execute other selected tweaks # Execute other selected tweaks
foreach ($tweak in $Tweaks) { foreach ($tweak in $Tweaks) {
Write-Debug "This is a tweak to run $tweak count: $cnt" Write-Debug "This is a tweak to run $tweak count: $cnt"
Invoke-WinUtilTweaks $tweak Invoke-WinUtilTweaks $tweak
$cnt += 1 $cnt += 1
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($cnt/$Tweaks.Count) })
} }
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Write-Host "=================================" Write-Host "================================="
Write-Host "-- Tweaks are Finished ---" Write-Host "-- Tweaks are Finished ---"
Write-Host "=================================" Write-Host "================================="
@ -5164,12 +5314,21 @@ function Invoke-WPFundoall {
param($Tweaks, $DebugPreference) param($Tweaks, $DebugPreference)
$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" })
}
$cnt = 0
Foreach ($tweak in $tweaks){ Foreach ($tweak in $tweaks){
Invoke-WinUtilTweaks $tweak -undo $true Invoke-WinUtilTweaks $tweak -undo $true
$cnt += 1
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($cnt/$Tweaks.Count) })
} }
$sync.ProcessRunning = $false $sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ 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 "=================================="
@ -5365,8 +5524,14 @@ function Invoke-WPFUnInstall {
if($confirm -eq "No"){return} if($confirm -eq "No"){return}
Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $DebugPreference) param($PackagesToInstall, $DebugPreference)
if ($PackagesToInstall.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" })
}
$packagesWinget, $packagesChoco = { $packagesWinget, $packagesChoco = {
$packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new() $packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new()
$packagesChoco = [System.Collections.Generic.List`1[System.Object]]::new() $packagesChoco = [System.Collections.Generic.List`1[System.Object]]::new()
@ -5392,23 +5557,21 @@ function Invoke-WPFUnInstall {
Install-WinUtilProgramChoco -ProgramsToInstall $packagesChoco -Manage "Uninstalling" Install-WinUtilProgramChoco -ProgramsToInstall $packagesChoco -Manage "Uninstalling"
} }
$ButtonType = [System.Windows.MessageBoxButton]::OK
$MessageboxTitle = "Uninstalls are Finished "
$Messageboxbody = ("Done")
$MessageIcon = [System.Windows.MessageBoxImage]::Information
[System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon)
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" })
} }
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" })
} }
$sync.ProcessRunning = $False $sync.ProcessRunning = $False
} }
} }
function Invoke-WPFUpdatesdefault { function Invoke-WPFUpdatesdefault {
@ -14945,6 +15108,10 @@ Invoke-WPFRunspace -ScriptBlock {
# Print the logo # Print the logo
Invoke-WPFFormVariables Invoke-WPFFormVariables
# Progress bar in taskbaritem > Set-WinUtilProgressbar
$sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo
Set-WinUtilTaskbaritem -state "None"
# Set the titlebar # Set the titlebar
$sync["Form"].title = $sync["Form"].title + " " + $sync.version $sync["Form"].title = $sync["Form"].title + " " + $sync.version
# Set the commands that will run when the form is closed # Set the commands that will run when the form is closed
@ -15079,38 +15246,6 @@ Add-Type @"
} }
} }
# Using a TaskbarItem Overlay until someone figures out how to replace the icon correctly
# URL of the image
$imageUrl = "https://christitus.com/images/logo-full.png"
# Download the image
$imagePath = "$env:TEMP\logo-full.png"
Invoke-WebRequest -Uri $imageUrl -OutFile $imagePath
# Read the image file as a byte array
$imageBytes = [System.IO.File]::ReadAllBytes($imagePath)
# Convert the byte array to a Base64 string
$base64String = [System.Convert]::ToBase64String($imageBytes)
# Create a streaming image by streaming the base64 string to a bitmap streamsource
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($base64String)
$bitmap.EndInit()
$bitmap.Freeze()
# Ensure TaskbarItemInfo is created if not already
if (-not $sync["Form"].TaskbarItemInfo) {
$sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo
}
# Set the overlay icon for the taskbar
$sync["Form"].TaskbarItemInfo.Overlay = $bitmap
$rect = New-Object RECT $rect = New-Object RECT
[Window]::GetWindowRect($windowHandle, [ref]$rect) [Window]::GetWindowRect($windowHandle, [ref]$rect)
$width = $rect.Right - $rect.Left $width = $rect.Right - $rect.Left
@ -15249,6 +15384,27 @@ $sync["SearchBar"].Add_TextChanged({
$label.Visibility = "Collapsed"} $label.Visibility = "Collapsed"}
}) })
$cttpnglogo = "$env:LOCALAPPDATA\winutil\cttlogo.png"
$ctticologo = "$env:LOCALAPPDATA\winutil\cttlogo.ico"
if (-NOT (Test-Path -Path $cttpnglogo) -or -NOT (Test-Path -Path $ctticologo)) {
Invoke-WebRequest -Uri "https://christitus.com/images/logo-full.png" -OutFile $cttpnglogo
}
$cttpngcheckmark = "$env:LOCALAPPDATA\winutil\cttcheckmark.png"
$ctticocheckmark = "$env:LOCALAPPDATA\winutil\cttcheckmark.ico"
if (-NOT (Test-Path -Path $cttpngcheckmark) -or -NOT (Test-Path -Path $ctticocheckmark)) {
Invoke-WebRequest -Uri "https://christitus.com/images/checkmark.png" -OutFile $cttpngcheckmark
}
ConvertTo-Icon -bitmapPath $cttpnglogo -iconPath $ctticologo
Set-WinUtilTaskbaritem -overlay "logo" | Out-Null
$sync["Form"].icon = $cttpnglogo
$sync["Form"].Add_Activated({
Set-WinUtilTaskbaritem -overlay "logo"
})
# Define event handler for button click # Define event handler for button click
$sync["SettingsButton"].Add_Click({ $sync["SettingsButton"].Add_Click({
Write-Debug "SettingsButton clicked" Write-Debug "SettingsButton clicked"