diff --git a/functions/private/Get-WinUtilRegistry.ps1 b/functions/private/Get-WinUtilRegistry.ps1 index 99b8e2f7..9a39795c 100644 --- a/functions/private/Get-WinUtilRegistry.ps1 +++ b/functions/private/Get-WinUtilRegistry.ps1 @@ -7,7 +7,7 @@ function Get-WinUtilRegistry { .EXAMPLE Get-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" - #> + #> param ( $Name, $Path, @@ -15,7 +15,7 @@ function Get-WinUtilRegistry { $Value ) - Try{ + Try{ $syscheckvalue = Get-ItemPropertyValue -Path $Path -Value $Value # Return Value } diff --git a/functions/private/Get-WinUtilVariables.ps1 b/functions/private/Get-WinUtilVariables.ps1 index d19a3e9e..d612e57c 100644 --- a/functions/private/Get-WinUtilVariables.ps1 +++ b/functions/private/Get-WinUtilVariables.ps1 @@ -1,32 +1,32 @@ function Get-WinUtilVariables { <# + .SYNOPSIS Gets every form object of the provided type .OUTPUTS List containing every object that matches the provided type + #> param ( [Parameter()] - [string[]]$Type + [ValidateSet("CheckBox", "Button")] + [string]$Type ) - $keys = $sync.keys | Where-Object { $_ -like "WPF*" } + $keys = $sync.keys | Where-Object {$psitem -like "WPF*"} - if ($Type) { + if($type){ $output = $keys | ForEach-Object { - Try { - $objType = $sync["$psitem"].GetType().Name - if ($Type -contains $objType) { + Try{ + if ($sync["$psitem"].GetType() -like "*$type*"){ Write-Output $psitem } } - Catch { - <#I am here so errors don't get outputted for a couple variables that don't have the .GetType() attribute#> - } + Catch{<#I am here so errors don't get outputted for a couple variables that don't have the .GetType() attribute#>} } - return $output + return $output } return $keys } diff --git a/functions/private/Install-WinUtilChoco.ps1 b/functions/private/Install-WinUtilChoco.ps1 index b96fc0e5..e0890489 100644 --- a/functions/private/Install-WinUtilChoco.ps1 +++ b/functions/private/Install-WinUtilChoco.ps1 @@ -7,23 +7,24 @@ function Install-WinUtilChoco { #> - try { + try{ Write-Host "Checking if Chocolatey is Installed..." if((Test-WinUtilPackageManager -choco)){ Write-Host "Chocolatey Already Installed" return } - - Write-Host "Seems Chocolatey is not installed, installing now" - Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -ErrorAction Stop - powershell choco feature enable -n allowGlobalConfirmation - + + Write-Host "Seems Chocolatey is not installed, installing now?" + # Let user decide if they want to install Chocolatey + $confirmation = Read-Host "Are you Sure You Want To Proceed:(y/n)" + if ($confirmation -eq 'y') { + Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -ErrorAction Stop + powershell choco feature enable -n allowGlobalConfirmation + } } - Catch { - Write-Host "===========================================" - Write-Host "-- Chocolatey failed to install ---" - Write-Host "===========================================" + Catch{ + throw [ChocoFailedInstall]::new('Failed to install') } } diff --git a/functions/private/Install-WinUtilWinget.ps1 b/functions/private/Install-WinUtilWinget.ps1 index 4be11a82..b04e6d94 100644 --- a/functions/private/Install-WinUtilWinget.ps1 +++ b/functions/private/Install-WinUtilWinget.ps1 @@ -1,9 +1,9 @@ function Get-LatestHash { $shaUrl = ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt$' }).browser_download_url - + $shaFile = Join-Path -Path $tempFolder -ChildPath 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt' $WebClient.DownloadFile($shaUrl, $shaFile) - + Get-Content $shaFile } @@ -14,8 +14,6 @@ function Install-WinUtilWinget { .SYNOPSIS Installs Winget if it is not already installed - .DESCRIPTION - This function will download the latest version of winget and install it. If winget is already installed, it will do nothing. #> Try{ Write-Host "Checking if Winget is Installed..." @@ -40,8 +38,8 @@ function Install-WinUtilWinget { } Write-Host "Running Alternative Installer and Direct Installing" - Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget" - + Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "irm https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/winget.ps1 | iex" + Write-Host "Winget Installed" } Catch{ diff --git a/functions/private/Set-WinUtilRestorePoint.ps1 b/functions/private/Set-WinUtilRestorePoint.ps1 new file mode 100644 index 00000000..ad80be96 --- /dev/null +++ b/functions/private/Set-WinUtilRestorePoint.ps1 @@ -0,0 +1,40 @@ +function Set-WinUtilRestorePoint { + <# + + .SYNOPSIS + Creates a Restore Point + + #> + + # Check if the user has administrative privileges + if (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Host "Please run this script as an administrator." + return + } + + # Check if System Restore is enabled for the main drive + try { + # Try getting restore points to check if System Restore is enabled + Enable-ComputerRestore -Drive "$env:SystemDrive" + } catch { + Write-Host "An error occurred while enabling System Restore: $_" + } + + # Check if the SystemRestorePointCreationFrequency value exists + $exists = Get-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore" -name "SystemRestorePointCreationFrequency" -ErrorAction SilentlyContinue + if($null -eq $exists){ + write-host 'Changing system to allow multiple restore points per day' + Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore" -Name "SystemRestorePointCreationFrequency" -Value "0" -Type DWord -Force -ErrorAction Stop | Out-Null + } + + # Get all the restore points for the current day + $existingRestorePoints = Get-ComputerRestorePoint | Where-Object { $_.CreationTime.Date -eq (Get-Date).Date } + + # Check if there is already a restore point created today + if ($existingRestorePoints.Count -eq 0) { + $description = "System Restore Point created by WinUtil" + + Checkpoint-Computer -Description $description -RestorePointType "MODIFY_SETTINGS" + Write-Host -ForegroundColor Green "System Restore Point Created Successfully" + } +} diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index 1460a6be..b25d1531 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -9,8 +9,8 @@ function Invoke-WPFButton { The name of the button that was clicked #> - - Param ([string]$Button) + + Param ([string]$Button) # Use this to get the name of the button #[System.Windows.MessageBox]::Show("$Button","Chris Titus Tech's Windows Utility","OK","Info") @@ -24,11 +24,16 @@ function Invoke-WPFButton { "WPFdesktop" {Invoke-WPFPresets "Desktop"} "WPFlaptop" {Invoke-WPFPresets "laptop"} "WPFminimal" {Invoke-WPFPresets "minimal"} + "WPFexport" {Invoke-WPFImpex -type "export" -CheckBox "WPFTweaks"} + "WPFimport" {Invoke-WPFImpex -type "import" -CheckBox "WPFTweaks"} + "WPFexportWinget" {Invoke-WPFImpex -type "export" -CheckBox "WPFInstall"} + "WPFimportWinget" {Invoke-WPFImpex -type "import" -CheckBox "WPFInstall"} "WPFclear" {Invoke-WPFPresets -preset $null -imported $true} "WPFclearWinget" {Invoke-WPFPresets -preset $null -imported $true -CheckBox "WPFInstall"} "WPFtweaksbutton" {Invoke-WPFtweaksbutton} "WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enabled"} "WPFRemoveUltPerf" {Invoke-WPFUltimatePerformance -State "Disabled"} + "WPFToggleDarkMode" {Invoke-WPFDarkMode -DarkMoveEnabled $(Get-WinUtilDarkMode)} "WPFundoall" {Invoke-WPFundoall} "WPFFeatureInstall" {Invoke-WPFFeatureInstall} "WPFPanelDISM" {Invoke-WPFPanelDISM} @@ -42,15 +47,11 @@ function Invoke-WPFButton { "WPFPaneluser" {Invoke-WPFControlPanel -Panel $button} "WPFUpdatesdefault" {Invoke-WPFUpdatesdefault} "WPFFixesUpdate" {Invoke-WPFFixesUpdate} - "WPFFixesWinget" {Invoke-WPFFixesWinget} "WPFFixesNetwork" {Invoke-WPFFixesNetwork} "WPFUpdatesdisable" {Invoke-WPFUpdatesdisable} "WPFUpdatessecurity" {Invoke-WPFUpdatessecurity} "WPFWinUtilShortcut" {Invoke-WPFShortcut -ShortcutToAdd "WinUtil"} "WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"} "WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"} - "WPFGetIso" {Invoke-WPFGetIso} - "WPFMicrowin" {Invoke-WPFMicrowin} - "WPFCloseButton" {Invoke-WPFCloseButton} } } \ No newline at end of file diff --git a/functions/public/Invoke-WPFInstall.ps1 b/functions/public/Invoke-WPFInstall.ps1 index 12362b12..f8b87bd7 100644 --- a/functions/public/Invoke-WPFInstall.ps1 +++ b/functions/public/Invoke-WPFInstall.ps1 @@ -7,12 +7,12 @@ function Invoke-WPFInstall { #> if($sync.ProcessRunning){ - $msg = "[Invoke-WPFInstall] Install process is currently running." + $msg = "Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } - $WingetInstall = (Get-WinUtilCheckBoxes)["Install"] + $WingetInstall = Get-WinUtilCheckBoxes -Group "WPFInstall" if ($wingetinstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install" @@ -20,15 +20,24 @@ function Invoke-WPFInstall { return } - Invoke-WPFRunspace -ArgumentList $WingetInstall,$DebugPreference -ScriptBlock { - param($WingetInstall, $DebugPreference) - + Invoke-WPFRunspace -ArgumentList $WingetInstall -scriptblock { + param($WingetInstall) try{ $sync.ProcessRunning = $true + # Ensure winget is installed Install-WinUtilWinget + + # Install all selected programs in new window Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall + $ButtonType = [System.Windows.MessageBoxButton]::OK + $MessageboxTitle = "Installs are Finished " + $Messageboxbody = ("Done") + $MessageIcon = [System.Windows.MessageBoxImage]::Information + + [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) + Write-Host "===========================================" Write-Host "-- Installs have finished ---" Write-Host "===========================================" @@ -38,7 +47,6 @@ function Invoke-WPFInstall { Write-Host "-- Winget failed to install ---" Write-Host "===========================================" } - Start-Sleep -Seconds 5 $sync.ProcessRunning = $False } } \ No newline at end of file diff --git a/functions/public/Invoke-WPFRunspace.ps1 b/functions/public/Invoke-WPFRunspace.ps1 index cb624ef3..9d16dac8 100644 --- a/functions/public/Invoke-WPFRunspace.ps1 +++ b/functions/public/Invoke-WPFRunspace.ps1 @@ -21,9 +21,8 @@ function Invoke-WPFRunspace { [CmdletBinding()] Param ( $ScriptBlock, - $ArgumentList, - $DebugPreference - ) + $ArgumentList + ) # Create a PowerShell instance $script:powershell = [powershell]::Create() @@ -31,9 +30,8 @@ function Invoke-WPFRunspace { # Add Scriptblock and Arguments to runspace $script:powershell.AddScript($ScriptBlock) $script:powershell.AddArgument($ArgumentList) - $script:powershell.AddArgument($DebugPreference) # Pass DebugPreference to the script block $script:powershell.RunspacePool = $sync.runspace - + # Execute the RunspacePool $script:handle = $script:powershell.BeginInvoke() diff --git a/functions/public/Invoke-WPFToggle.ps1 b/functions/public/Invoke-WPFToggle.ps1 index 826abeaa..23e26f28 100644 --- a/functions/public/Invoke-WPFToggle.ps1 +++ b/functions/public/Invoke-WPFToggle.ps1 @@ -9,8 +9,8 @@ function Invoke-WPFToggle { The name of the toggle to invoke #> - - Param ([string]$Button) + + Param ([string]$Button) # Use this to get the name of the button #[System.Windows.MessageBox]::Show("$Button","Chris Titus Tech's Windows Utility","OK","Info") @@ -19,10 +19,6 @@ function Invoke-WPFToggle { "WPFToggleDarkMode" {Invoke-WinUtilDarkMode -DarkMoveEnabled $(Get-WinUtilToggleStatus WPFToggleDarkMode)} "WPFToggleBingSearch" {Invoke-WinUtilBingSearch $(Get-WinUtilToggleStatus WPFToggleBingSearch)} - "WPFToggleNumLock" {Invoke-WinUtilNumLock $(Get-WinUtilToggleStatus WPFToggleNumLock)} - "WPFToggleVerboseLogon" {Invoke-WinUtilVerboseLogon $(Get-WinUtilToggleStatus WPFToggleVerboseLogon)} - "WPFToggleShowExt" {Invoke-WinUtilShowExt $(Get-WinUtilToggleStatus WPFToggleShowExt)} - "WPFToggleSnapFlyout" {Invoke-WinUtilSnapFlyout $(Get-WinUtilToggleStatus WPFToggleSnapFlyout)} - "WPFToggleMouseAcceleration" {Invoke-WinUtilMouseAcceleration $(Get-WinUtilToggleStatus WPFToggleMouseAcceleration)} + } } \ No newline at end of file diff --git a/functions/public/Invoke-WPFUnInstall.ps1 b/functions/public/Invoke-WPFUnInstall.ps1 index af69a964..5ab22920 100644 --- a/functions/public/Invoke-WPFUnInstall.ps1 +++ b/functions/public/Invoke-WPFUnInstall.ps1 @@ -7,12 +7,12 @@ function Invoke-WPFUnInstall { #> if($sync.ProcessRunning){ - $msg = "[Invoke-WPFUnInstall] Install process is currently running" + $msg = "Install process is currently running" [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } - $WingetInstall = (Get-WinUtilCheckBoxes)["Install"] + $WingetInstall = Get-WinUtilCheckBoxes -Group "WPFInstall" if ($wingetinstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install" @@ -29,9 +29,8 @@ function Invoke-WPFUnInstall { if($confirm -eq "No"){return} - Invoke-WPFRunspace -ArgumentList $WingetInstall,$DebugPreference -ScriptBlock { - param($WingetInstall, $DebugPreference) - + Invoke-WPFRunspace -ArgumentList $WingetInstall -scriptblock { + param($WingetInstall) try{ $sync.ProcessRunning = $true @@ -42,7 +41,7 @@ function Invoke-WPFUnInstall { $MessageboxTitle = "Uninstalls are Finished " $Messageboxbody = ("Done") $MessageIcon = [System.Windows.MessageBoxImage]::Information - + [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) Write-Host "===========================================" diff --git a/pester/winutil.Tests.ps1 b/pester/winutil.Tests.ps1 new file mode 100644 index 00000000..0283b61e --- /dev/null +++ b/pester/winutil.Tests.ps1 @@ -0,0 +1,27 @@ +# Load Variables needed for testing + +./Compile.ps1 + +$script = Get-Content .\winutil.ps1 +# Remove the part of the script that shows the form, leaving only the variable and function declarations +$script[0..($script.count - 21)] | Out-File .\pester.ps1 + + +BeforeAll { + # Execute the truncated script, bringing the variabes into the current scope + . .\pester.ps1 +} + +Describe "GUI" { + Context "XML" { + It "Imports with no errors" { + $inputXML | should -Not -BeNullOrEmpty + } + } + + Context "Form" { + It "Imports with no errors" { + $sync.Form | should -Not -BeNullOrEmpty + } + } +} diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 85bf37b8..39f1b0c7 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,4 +1,5 @@ # SPDX-License-Identifier: MIT + # Set the maximum number of threads for the RunspacePool to the number of threads on the machine $maxthreads = [int]$env:NUMBER_OF_PROCESSORS @@ -36,7 +37,7 @@ $sync.runspace.Open() WingetFailedInstall($Message) : base($Message) {} } - + class ChocoFailedInstall : Exception { [string] $additionalData @@ -48,67 +49,17 @@ $sync.runspace.Open() GenericException($Message) : base($Message) {} } - + $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^`n" - $sortedApps = $organizedData[$panel][$category].Keys | Sort-Object - foreach ($appName in $sortedApps) { - $appInfo = $organizedData[$panel][$category][$appName] - if ($null -eq $appInfo.Link) - { - $blockXml += "`n" - } - else - { - $blockXml += "`n" - } - } - } - - $inputXML = $inputXML -replace "{{InstallPanel$panel}}", $blockXml - $blockXml = "" -} - -if ((Get-WinUtilToggleStatus WPFToggleDarkMode) -eq $True) { +if ((Get-WinUtilToggleStatus WPFToggleDarkMode) -eq $True){ $ctttheme = 'Matrix' } -else { +Else{ $ctttheme = 'Classic' } + $inputXML = Set-WinUtilUITheme -inputXML $inputXML -themeName $ctttheme [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') @@ -136,8 +87,22 @@ $xaml.SelectNodes("//*[@Name]") | ForEach-Object {$sync["$("$($psitem.Name)")"] $sync.keys | ForEach-Object { if($sync.$psitem){ - if($($sync["$psitem"].GetType() | Select-Object -ExpandProperty Name) -eq "CheckBox" ` - -and $sync["$psitem"].Name -like "WPFToggle*"){ + if($($sync["$psitem"].GetType() | Select-Object -ExpandProperty Name) -eq "Button"){ + $sync["$psitem"].Add_Click({ + [System.Object]$Sender = $args[0] + Invoke-WPFButton $Sender.name + }) + } + } +} + + +$sync.keys | ForEach-Object { + if($sync.$psitem){ + if( + $($sync["$psitem"].GetType() | Select-Object -ExpandProperty Name) -eq "CheckBox" ` + -and $sync["$psitem"].Name -like "WPFToggle*" + ){ $sync["$psitem"].IsChecked = Get-WinUtilToggleStatus $sync["$psitem"].Name $sync["$psitem"].Add_Click({ @@ -145,34 +110,10 @@ $sync.keys | ForEach-Object { Invoke-WPFToggle $Sender.name }) } - - if($($sync["$psitem"].GetType() | Select-Object -ExpandProperty Name) -eq "ToggleButton"){ - $sync["$psitem"].Add_Click({ - [System.Object]$Sender = $args[0] - Invoke-WPFButton $Sender.name - }) - } - - if($($sync["$psitem"].GetType() | Select-Object -ExpandProperty Name) -eq "Button"){ - $sync["$psitem"].Add_Click({ - [System.Object]$Sender = $args[0] - Invoke-WPFButton $Sender.name - }) - } - - 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 - Write-Debug "Opening: $($Sender.ToolTip)" - }) - } - - } } } + #=========================================================================== # Setup background config #=========================================================================== @@ -180,7 +121,9 @@ $sync.keys | ForEach-Object { # Load computer information in the background Invoke-WPFRunspace -ScriptBlock { $sync.ConfigLoaded = $False + $sync.ComputerInfo = Get-ComputerInfo + $sync.ConfigLoaded = $True } | Out-Null @@ -192,7 +135,14 @@ Invoke-WPFRunspace -ScriptBlock { Invoke-WPFFormVariables # Check if Chocolatey is installed -Install-WinUtilChoco +try{ + Install-WinUtilChoco +} +Catch [ChocoFailedInstall]{ + Write-Host "===========================================" + Write-Host "-- Chocolatey failed to install ---" + Write-Host "===========================================" +} # Set the titlebar $sync["Form"].title = $sync["Form"].title + " " + $sync.version @@ -203,299 +153,7 @@ $sync["Form"].Add_Closing({ [System.GC]::Collect() }) -# Attach the event handler to the Click event -$sync.CheckboxFilterClear.Add_Click({ - $sync.CheckboxFilter.Text = "" - $sync.CheckboxFilterClear.Visibility = "Collapsed" -}) - -# add some shortcuts for people that don't like clicking -$commonKeyEvents = { - if ($sync.ProcessRunning -eq $true) { - return - } - - if ($_.Key -eq "Escape") - { - $sync.CheckboxFilter.SelectAll() - $sync.CheckboxFilter.Text = "" - $sync.CheckboxFilterClear.Visibility = "Collapsed" - return - } - - # don't ask, I know what I'm doing, just go... - if (($_.Key -eq "Q" -and $_.KeyboardDevice.Modifiers -eq "Ctrl")) - { - $this.Close() - } - if ($_.KeyboardDevice.Modifiers -eq "Alt") { - if ($_.SystemKey -eq "I") { - Invoke-WPFButton "WPFTab1BT" - } - if ($_.SystemKey -eq "T") { - Invoke-WPFButton "WPFTab2BT" - } - if ($_.SystemKey -eq "C") { - Invoke-WPFButton "WPFTab3BT" - } - if ($_.SystemKey -eq "U") { - Invoke-WPFButton "WPFTab4BT" - } - if ($_.SystemKey -eq "M") { - Invoke-WPFButton "WPFTab5BT" - } - if ($_.SystemKey -eq "P") { - Write-Host "Your Windows Product Key: $((Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey)" - } - } - # shortcut for the filter box - if ($_.Key -eq "F" -and $_.KeyboardDevice.Modifiers -eq "Ctrl") { - if ($sync.CheckboxFilter.Text -eq "Ctrl-F to filter") { - $sync.CheckboxFilter.SelectAll() - $sync.CheckboxFilter.Text = "" - } - $sync.CheckboxFilter.Focus() - } -} - -$sync["Form"].Add_PreViewKeyDown($commonKeyEvents) - -$sync["Form"].Add_MouseLeftButtonDown({ - if ($sync["SettingsPopup"].IsOpen) { - $sync["SettingsPopup"].IsOpen = $false - } - $sync["Form"].DragMove() -}) - -$sync["Form"].Add_MouseDoubleClick({ - if ($sync["Form"].WindowState -eq [Windows.WindowState]::Normal) - { - $sync["Form"].WindowState = [Windows.WindowState]::Maximized; - } - else - { - $sync["Form"].WindowState = [Windows.WindowState]::Normal; - } -}) - -$sync["Form"].Add_Deactivated({ - Write-Debug "WinUtil lost focus" - if ($sync["SettingsPopup"].IsOpen) { - $sync["SettingsPopup"].IsOpen = $false - } -}) - -$sync["Form"].Add_ContentRendered({ - - try { - [void][Window] - } catch { -Add-Type @" - using System; - using System.Runtime.InteropServices; - public class Window { - [DllImport("user32.dll")] - public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw); - - [DllImport("user32.dll")] - public static extern int GetSystemMetrics(int nIndex); - }; - public struct RECT { - public int Left; // x position of upper-left corner - public int Top; // y position of upper-left corner - public int Right; // x position of lower-right corner - public int Bottom; // y position of lower-right corner - } -"@ - } - - foreach ($proc in (Get-Process | Where-Object { $_.MainWindowTitle -and $_.MainWindowTitle -like "*titus*" })) { - if ($proc.Id -ne [System.IntPtr]::Zero) { - Write-Debug "MainWindowHandle: $($proc.Id) $($proc.MainWindowTitle) $($proc.MainWindowHandle)" - $windowHandle = $proc.MainWindowHandle - } - } - - # need to experiemnt more - # setting icon for the windows is still not working - # $pngUrl = "https://christitus.com/images/logo-full.png" - # $pngPath = "$env:TEMP\cttlogo.png" - # $iconPath = "$env:TEMP\cttlogo.ico" - # # Download the PNG file - # Invoke-WebRequest -Uri $pngUrl -OutFile $pngPath - # if (Test-Path -Path $pngPath) { - # ConvertTo-Icon -bitmapPath $pngPath -iconPath $iconPath - # } - # $icon = [System.Drawing.Icon]::ExtractAssociatedIcon($iconPath) - # Write-Host $icon.Handle - # [Window]::SendMessage($windowHandle, 0x80, [IntPtr]::Zero, $icon.Handle) - - $rect = New-Object RECT - [Window]::GetWindowRect($windowHandle, [ref]$rect) - $width = $rect.Right - $rect.Left - $height = $rect.Bottom - $rect.Top - - Write-Debug "UpperLeft:$($rect.Left),$($rect.Top) LowerBottom:$($rect.Right),$($rect.Bottom). Width:$($width) Height:$($height)" - - # 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 - - # Print the screen size - Write-Debug "Primary Monitor Width: $screenWidth pixels" - Write-Debug "Primary Monitor Height: $screenHeight pixels" - - # Compare with the primary monitor size - if ($width -gt $screenWidth -or $height -gt $screenHeight) { - Write-Debug "The specified width and/or height is greater than the primary monitor size." - [void][Window]::MoveWindow($windowHandle, 0, 0, $screenWidth, $screenHeight, $True) - } else { - Write-Debug "The specified width and height are within the primary monitor size limits." - } - } else { - Write-Debug "Unable to retrieve information about the primary monitor." - } - - Invoke-WPFTab "WPFTab1BT" - $sync["Form"].Focus() - - # maybe this is not the best place to load and execute config file? - # maybe community can help? - if ($PARAM_CONFIG){ - Invoke-WPFImpex -type "import" -Config $PARAM_CONFIG - if ($PARAM_RUN){ - while ($sync.ProcessRunning) { - Start-Sleep -Seconds 5 - } - Start-Sleep -Seconds 5 - - Write-Host "Applying tweaks..." - Invoke-WPFtweaksbutton - while ($sync.ProcessRunning) { - Start-Sleep -Seconds 5 - } - Start-Sleep -Seconds 5 - - Write-Host "Installing features..." - Invoke-WPFFeatureInstall - while ($sync.ProcessRunning) { - Start-Sleep -Seconds 5 - } - - Start-Sleep -Seconds 5 - Write-Host "Installing applications..." - while ($sync.ProcessRunning) { - Start-Sleep -Seconds 1 - } - Invoke-WPFInstall - Start-Sleep -Seconds 5 - - Write-Host "Done." - } - } - -}) - -$sync["CheckboxFilter"].Add_TextChanged({ - - if ($sync.CheckboxFilter.Text -ne "") { - $sync.CheckboxFilterClear.Visibility = "Visible" - } - else { - $sync.CheckboxFilterClear.Visibility = "Collapsed" - } - - $filter = Get-WinUtilVariables -Type CheckBox - $CheckBoxes = $sync.GetEnumerator() | Where-Object { $psitem.Key -in $filter } - - foreach ($CheckBox in $CheckBoxes) { - # Check if the checkbox is null or if it doesn't have content - if ($CheckBox -eq $null -or $CheckBox.Value -eq $null -or $CheckBox.Value.Content -eq $null) { - continue - } - - $textToSearch = $sync.CheckboxFilter.Text - $checkBoxName = $CheckBox.Key - $textBlockName = $checkBoxName + "Link" - - # Retrieve the corresponding text block based on the generated name - $textBlock = $sync[$textBlockName] - - if ($CheckBox.Value.Content.ToLower().Contains($textToSearch)) { - $CheckBox.Value.Visibility = "Visible" - # Set the corresponding text block visibility - if ($textBlock -ne $null) { - $textBlock.Visibility = "Visible" - } - } - else { - $CheckBox.Value.Visibility = "Collapsed" - # Set the corresponding text block visibility - if ($textBlock -ne $null) { - $textBlock.Visibility = "Collapsed" - } - } - } - -}) - -# Define event handler for button click -$sync["SettingsButton"].Add_Click({ - Write-Debug "SettingsButton clicked" - if ($sync["SettingsPopup"].IsOpen) { - $sync["SettingsPopup"].IsOpen = $false - } - else { - $sync["SettingsPopup"].IsOpen = $true - } - $_.Handled = $false -}) - -# Define event handlers for menu items -$sync["ImportMenuItem"].Add_Click({ - # Handle Import menu item click - Write-Debug "Import clicked" - $sync["SettingsPopup"].IsOpen = $false - Invoke-WPFImpex -type "import" - $_.Handled = $false -}) - -$sync["ExportMenuItem"].Add_Click({ - # Handle Export menu item click - Write-Debug "Export clicked" - $sync["SettingsPopup"].IsOpen = $false - Invoke-WPFImpex -type "export" - $_.Handled = $false -}) - -$sync["AboutMenuItem"].Add_Click({ - # Handle Export menu item click - Write-Debug "About clicked" - $sync["SettingsPopup"].IsOpen = $false - # Example usage - $authorInfo = @" -Author : @christitustech -Runspace : @DeveloperDurp -GUI : @KonTy -MicroWin : @KonTy -GitHub : https://github.com/ChrisTitusTech/winutil -Version : $($sync.version) -"@ - Show-CustomDialog -Message $authorInfo -Width 400 -}) - +# Show the form $sync["Form"].ShowDialog() | out-null + Stop-Transcript \ No newline at end of file diff --git a/scripts/start.ps1 b/scripts/start.ps1 index 5f216172..2f3f5156 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -5,36 +5,10 @@ GitHub : https://github.com/ChrisTitusTech Version : #{replaceme} #> -param ( - [switch]$Debug, - [string]$Config, - [switch]$Run -) - -# Set DebugPreference based on the -Debug switch -if ($Debug) { - $DebugPreference = "Continue" -} - -if ($Config) { - $PARAM_CONFIG = $Config -} - -$PARAM_RUN = $false -# Handle the -Run switch -if ($Run) { - Write-Host "Running config file tasks..." - $PARAM_RUN = $true -} - -if (!(Test-Path -Path $ENV:TEMP)) { - New-Item -ItemType Directory -Force -Path $ENV:TEMP -} Start-Transcript $ENV:TEMP\Winutil.log -Append # Load DLLs -Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName System.Windows.Forms # Variable to sync between runspaces @@ -44,21 +18,9 @@ $sync.version = "#{replaceme}" $sync.configs = @{} $sync.ProcessRunning = $false -$currentPid = [System.Security.Principal.WindowsIdentity]::GetCurrent() -$principal = new-object System.Security.Principal.WindowsPrincipal($currentPid) -$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator - -if ($principal.IsInRole($adminRole)) -{ - $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Admin)" - clear-host -} -else -{ - $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell"; - $newProcess.Arguments = $myInvocation.MyCommand.Definition; - $newProcess.Verb = "runas"; - [System.Diagnostics.Process]::Start($newProcess); +if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Output "Winutil needs to be run as Administrator. Attempting to relaunch." + Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "iwr -useb https://christitus.com/win | iex" break -} \ No newline at end of file +}