From d0bde83333730a4536497451af747daba11e5039 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Thu, 19 Oct 2023 17:12:55 -0500 Subject: [PATCH] 2023 09 23 test (#1117) * move restore point to runspace (#1056) * Add Guilded into Communication Tab (#1059) * Add Guilded into Communication Tab * Remove Choco Package due to there is no Chocolatey packages * : Add ZeroTier One to utilities menu (#1061) * Update applications.json (#1063) Update to add [SuperF4 - Stefan Sundin](https://stefansundin.github.io/superf4/), as mentioned in #374 [Choco - SuperF4](https://community.chocolatey.org/packages/superf4) maintained by Xav83. [WinGet - SuperF4](https://winstall.app/apps/StefanSundin.Superf4) SuperF4 and Winget package published by Stefan Sundin. * Update inputXML.xaml (#1062) Updated inputXML.xaml to account for addition of the SuperF4 software. * Added AIMP music player (#1064) * Add Ventoy (Chocolatey Only Package) & .NET Core Runtime (Winget & Chocolatey) (#1066) * Tidy up SuperF4 line. * Tidy up SuperF4 line. Used spaces instead of tabs. * Add dotnet 7.0.11 Desktop Runtime * Undone changes to SuperF4 line * Addition of Ventoy (chocolatey only) package * Comment Spacing, Indentation, and Capitalization (#1084) * Comment Spacing, Indentation, and Capitalization * Comment Grammar and Spacing Makes grammar in comments better and more consistent Adds space before comment and centers word in `Write-Host` commands * More Grammar and Formatting * Add some comments * Populate PlaceHolder comments in functions Files I found that has issues: Get-WinUtilRegistry.ps1 Install-WinUtilWinget.ps1 Invoke-WinUtilDarkMode.ps1 Remove-WinUtilAPPX.ps1 Test-WinUtilPackageManager.ps1 Update-WinUtilProgramWinget.ps1 Invoke-WPFUpdatessecurity.ps1 * Tweak a few more comments * Tweak another write-host statement * Undo Catch statement adjustment It's outside of the scope of this pull request * Trim Trailing Whitespace (#1085) * Trim Trailing Whitespace * Revert "Trim Trailing Whitespace" This reverts commit 0ce32aa2c2fbf860138856375bdea05e119c36f4. * Trim Trailing Whitespace, take 2 * Bug Fixes - Edge Removal pullback to local - Formatting fixes * testing refactor to ps1 * Update winget-install to 3.0.1 (#1086) * Update tweaks.json (#1087) Capitalized first letter of "path" --> "Path" keys * Update edgeremoval.ps1 * Update edgeremoval.ps1 * Update edgeremoval.ps1 add error handling * Update functions.Tests.ps1 * fix catch error * add MSI Afterburner (#1097) * Add GitHub stats * Remove Application Experience * Thorium addition * remove sample submission * testing * Ultimate Performance * Home GPEDIT * Fix Winget Install on New System --------- Co-authored-by: DeveloperDurp Co-authored-by: Justawildwolf <62820836+blusewill@users.noreply.github.com> Co-authored-by: Tim Stone Co-authored-by: Will Barnard <5012445+mrwillbarnz@users.noreply.github.com> Co-authored-by: Ian Bassi Co-authored-by: Carter <60557606+Carterpersall@users.noreply.github.com> Co-authored-by: Yorai Levi Co-authored-by: Saikrishnan K <53394202+K-Saikrishnan@users.noreply.github.com> --- Compile.ps1 | 4 +- README.md | 3 + config/applications.json | 36 +- config/feature.json | 2 +- config/helperscript.ps1 | 68 +- config/tweaks.json | 90 +- edgeremoval.bat | 236 ++++ edgeremoval.ps1 | 466 ++++++++ functions/private/Get-WinUtilCheckBoxes.ps1 | 22 +- .../private/Get-WinUtilInstallerProcess.ps1 | 14 +- functions/private/Get-WinUtilRegistry.ps1 | 15 +- functions/private/Get-WinUtilToggleStatus.ps1 | 19 +- functions/private/Get-WinUtilVariables.ps1 | 15 +- functions/private/Install-WinUtilChoco.ps1 | 29 +- .../private/Install-WinUtilProgramWinget.ps1 | 21 +- functions/private/Install-WinUtilWinget.ps1 | 26 +- .../private/Invoke-WinUtilBingSearch.ps1 | 13 +- .../private/Invoke-WinUtilCurrentSystem.ps1 | 19 +- functions/private/Invoke-WinUtilDarkMode.ps1 | 15 +- .../private/Invoke-WinUtilFeatureInstall.ps1 | 18 +- functions/private/Invoke-WinUtilScript.ps1 | 19 +- functions/private/Invoke-WinUtilTweaks.ps1 | 16 +- functions/private/Remove-WinUtilAPPX.ps1 | 16 +- functions/private/Set-WinUtilDNS.ps1 | 14 +- functions/private/Set-WinUtilRegistry.ps1 | 25 +- functions/private/Set-WinUtilRestorePoint.ps1 | 12 +- .../private/Set-WinUtilScheduledTask.ps1 | 17 +- functions/private/Set-WinUtilService.ps1 | 23 +- functions/private/Set-WinUtilUiTheme.ps1 | 17 +- .../private/Test-WinUtilPackageManager.ps1 | 14 +- .../private/Update-WinUtilProgramWinget.ps1 | 8 +- functions/public/Invoke-WPFButton.ps1 | 21 +- functions/public/Invoke-WPFControlPanel.ps1 | 13 +- functions/public/Invoke-WPFFeatureInstall.ps1 | 14 +- functions/public/Invoke-WPFFixesNetwork.ps1 | 18 +- functions/public/Invoke-WPFFixesUpdate.ps1 | 16 +- functions/public/Invoke-WPFFormVariables.ps1 | 8 +- functions/public/Invoke-WPFGetInstalled.ps1 | 11 +- functions/public/Invoke-WPFImpex.ps1 | 19 +- functions/public/Invoke-WPFInstall.ps1 | 12 +- functions/public/Invoke-WPFInstallUpgrade.ps1 | 8 +- functions/public/Invoke-WPFPanelAutologin.ps1 | 8 +- functions/public/Invoke-WPFPanelDISM.ps1 | 25 +- functions/public/Invoke-WPFPresets.ps1 | 13 +- functions/public/Invoke-WPFRunspace.ps1 | 35 +- functions/public/Invoke-WPFShortcut.ps1 | 11 +- functions/public/Invoke-WPFTab.ps1 | 13 +- functions/public/Invoke-WPFToggle.ps1 | 21 +- .../public/Invoke-WPFUltimatePerformance.ps1 | 31 +- functions/public/Invoke-WPFUnInstall.ps1 | 20 +- functions/public/Invoke-WPFUpdatesdefault.ps1 | 14 +- functions/public/Invoke-WPFUpdatesdisable.ps1 | 13 +- .../public/Invoke-WPFUpdatessecurity.ps1 | 15 +- functions/public/Invoke-WPFtweaksbutton.ps1 | 12 +- functions/public/Invoke-WPFundoall.ps1 | 12 +- gpedit-home.ps1 | 4 + lint/PSScriptAnalyser.ps1 | 2 +- ooshutup10_winutil_settings.cfg | 8 +- pester/configs.Tests.ps1 | 34 +- pester/functions.Tests.ps1 | 8 +- pester/winutil.Tests.ps1 | 16 +- scripts/main.ps1 | 54 +- scripts/start.ps1 | 4 +- winget.ps1 | 31 +- winutil.ps1 | 1042 ++++++++++------- xaml/inputXML.xaml | 64 +- 66 files changed, 2041 insertions(+), 921 deletions(-) create mode 100644 edgeremoval.bat create mode 100644 edgeremoval.ps1 create mode 100644 gpedit-home.ps1 diff --git a/Compile.ps1 b/Compile.ps1 index 04c19e9d..d17b15af 100644 --- a/Compile.ps1 +++ b/Compile.ps1 @@ -23,13 +23,13 @@ Get-ChildItem .\functions -Recurse -File | ForEach-Object { Get-ChildItem .\xaml | ForEach-Object { $xaml = (Get-Content $psitem.FullName).replace("'","''") - + Write-output "`$$($psitem.BaseName) = '$xaml'" | Out-File ./$scriptname -Append -Encoding ascii } Get-ChildItem .\config | Where-Object {$psitem.extension -eq ".json"} | ForEach-Object { $json = (Get-Content $psitem.FullName).replace("'","''") - + Write-output "`$sync.configs.$($psitem.BaseName) = '$json' `| convertfrom-json" | Out-File ./$scriptname -Append -Encoding ascii } diff --git a/README.md b/README.md index ec818022..610af110 100644 --- a/README.md +++ b/README.md @@ -99,3 +99,6 @@ Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep roc [![Contributors](https://contrib.rocks/image?repo=ChrisTitusTech/winutil)](https://github.com/ChrisTitusTech/winutil/graphs/contributors) +## GitHub Stats + +![Alt](https://repobeats.axiom.co/api/embed/aad37eec9114c507f109d34ff8d38a59adc9503f.svg "Repobeats analytics image") \ No newline at end of file diff --git a/config/applications.json b/config/applications.json index 7644d1f4..194fc1bf 100755 --- a/config/applications.json +++ b/config/applications.json @@ -1,4 +1,4 @@ -{ +{ "WPFInstall7zip": { "winget": "7zip.7zip", "choco": "7zip" @@ -19,6 +19,10 @@ "winget": "AnyDeskSoftwareGmbH.AnyDesk", "choco": "anydesk" }, + "WPFInstallaimp": { + "winget": "AIMP.AIMP", + "choco": "aimp" + }, "WPFInstallaudacity": { "winget": "Audacity.Audacity", "choco": "audacity" @@ -91,6 +95,10 @@ "winget": "Microsoft.DotNet.DesktopRuntime.6", "choco": "dotnet-6.0-runtime" }, + "WPFInstalldotnet7": { + "winget": "Microsoft.DotNet.DesktopRuntime.7", + "choco": "dotnet-7.0-runtime" + }, "WPFInstalleaapp": { "winget": "ElectronicArts.EADesktop", "choco": "ea-app" @@ -143,6 +151,10 @@ "winget": "GIMP.GIMP", "choco": "gimp" }, + "WPFInstallguilded": { + "winget": "Guilded.Guilded", + "choco": "" + }, "WPFInstallgit": { "Winget": "Git.Git", "choco": "git" @@ -303,6 +315,10 @@ "winget": "mRemoteNG.mRemoteNG", "choco": "mremoteng" }, + "WPFInstallmsiafterburner": { + "winget": "Guru3D.Afterburner", + "choco": "msiafterburner" + }, "WPFInstallmusicbee": { "winget": "MusicBee.MusicBee", "choco": "musicbee" @@ -491,6 +507,10 @@ "winget": "SumatraPDF.SumatraPDF", "choco": "sumatrapdf" }, + "WPFInstallsuperf4": { + "winget": "StefanSundin.Superf4", + "choco": "superf4" + }, "WPFInstalltcpview": { "winget": "Microsoft.Sysinternals.TCPView", "choco": "tcpview" @@ -511,6 +531,10 @@ "winget": "Microsoft.WindowsTerminal", "choco": "microsoft-windows-terminal" }, + "WPFInstallthorium": { + "winget": "Alex313031.Thorium", + "choco": "na" + }, "WPFInstalltor": { "Winget": "TorProject.TorBrowser", "choco": "tor-browser" @@ -530,7 +554,7 @@ "WPFInstalltidal": { "Winget": "9NNCB5BS59PH", "choco": "na" - }, + }, "WPFInstallubisoft": { "winget": "Ubisoft.Connect", "choco": "ubisoft-connect" @@ -547,6 +571,10 @@ "winget": "Microsoft.VCRedist.2015+.x64", "choco": "na" }, + "WPFInstallventoy": { + "winget": "na", + "choco": "ventoy" + }, "WPFInstallviber": { "Winget": "Viber.Viber", "choco": "viber" @@ -611,6 +639,10 @@ "winget": "subhra74.XtremeDownloadManager", "choco": "xdm" }, + "WPFInstallzerotierone": { + "winget": "ZeroTier.ZeroTierOne", + "choco": "zerotier-one" + }, "WPFInstallzoom": { "winget": "Zoom.Zoom", "choco": "zoom" diff --git a/config/feature.json b/config/feature.json index 3707c66e..1bb7f09f 100644 --- a/config/feature.json +++ b/config/feature.json @@ -40,7 +40,7 @@ "Microsoft-Windows-Subsystem-Linux" ], "InvokeScript": [ - + ] }, "WPFFeaturenfs": { diff --git a/config/helperscript.ps1 b/config/helperscript.ps1 index a0b633cb..1b1b6d7a 100644 --- a/config/helperscript.ps1 +++ b/config/helperscript.ps1 @@ -1,4 +1,4 @@ -#This file is meant to assist in building out the json files inside this folder. +# This file is meant to assist in building out the json files inside this folder. #=========================================================================== # applications.json @@ -35,7 +35,7 @@ Example: #> -#Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. +# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. #------Do not delete WPF------ $NameofButton = "WPF" + "" @@ -45,7 +45,7 @@ $ChocoCommand = "" $ButtonToAdd = New-Object psobject $jsonfile = Get-Content ./config/applications.json | ConvertFrom-Json -#remove if already exists +# Remove if already exists if($jsonfile.$NameofButton){ $jsonfile.psobject.Properties.remove($NameofButton) } @@ -85,10 +85,10 @@ Example: "ClientForNFS-Infrastructure", "NFS-Administration" ] -} +} #> -#Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. +# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. $NameofButton = "" $commands = @( @@ -97,7 +97,7 @@ $commands = @( $jsonfile = Get-Content ./config/feature.json | ConvertFrom-Json -#remove if already exists +# Remove if already exists if($jsonfile.$NameofButton){ $jsonfile.psobject.Properties.remove($NameofButton) } @@ -147,19 +147,19 @@ Example: "EssTweaksServices", "EssTweaksTele" ] -} +} #> -#Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. +# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. $NameofButton = "WPF" + "" $commands = @( - + ) $jsonfile = Get-Content ./config/preset.json | ConvertFrom-Json -#remove if already exists +# Remove if already exists if($jsonfile.$NameofButton){ $jsonfile.psobject.Properties.remove($NameofButton) } @@ -186,21 +186,21 @@ $jsonfile | ConvertTo-Json | Out-File ./config/preset.json "Path": "Path in registry", "Name": "Name of Registry key", "Type": "Item type", - "Value": "Value to modify", + "Value": "Value to modify", "OriginalValue": "value to reset" } ], "service" : [ { "Name": "Name of service", - "StartupType": "Startup type to set", + "StartupType": "Startup type to set", "OriginalType": "Startup type to reset" } ], "ScheduledTask" : [ { "Name": "Path to scheduled task", - "State": "State to set", + "State": "State to set", "OriginalState": "State to reset" } ], @@ -211,10 +211,10 @@ $jsonfile | ConvertTo-Json | Out-File ./config/preset.json "InvokeScript": [ "Script to make modifications not possible with the above types Special care needs to be taken here as converting from json to a scriptblock - can cause weird issues. Please look at the example below to get an idea of how things should work" + can cause weird issues. Please look at the example below to get an idea of how things should work" ], "UndoScript": [ - "Same as above however is meant to undo what you did above" + "Same as above however is meant to undo what you did above" ] } } @@ -228,14 +228,14 @@ Example: "Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\System", "Name": "EnableActivityFeed", "Type": "DWord", - "Value": "0", + "Value": "0", "OriginalValue": "1" }, { "Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\System", "Name": "PublishUserActivities", "Type": "DWord", - "Value": "0", + "Value": "0", "OriginalValue": "1" } ] @@ -244,12 +244,12 @@ Example: "service" : [ { "Name": "HomeGroupListener", - "StartupType": "Manual", + "StartupType": "Manual", "OriginalType": "Automatic" }, { "Name": "HomeGroupProvider", - "StartupType": "Manual", + "StartupType": "Manual", "OriginalType": "Automatic" } ] @@ -258,12 +258,12 @@ Example: "ScheduledTask" : [ { "Name": "Microsoft\\Windows\\Application Experience\\Microsoft Compatibility Appraiser", - "State": "Disabled", + "State": "Disabled", "OriginalState": "Enabled" - }, + }, { "Name": "Microsoft\\Windows\\Application Experience\\ProgramDataUpdater", - "State": "Disabled", + "State": "Disabled", "OriginalState": "Enabled" } ] @@ -279,18 +279,18 @@ Example: "Import-Module BitsTransfer Start-BitsTransfer -Source \"https://raw.githubusercontent.com/ChrisTitusTech/win10script/master/ooshutup10.cfg\" -Destination C:\\Windows\\Temp\\ooshutup10.cfg Start-BitsTransfer -Source \"https://dl5.oo-software.com/files/ooshutup10/OOSU10.exe\" -Destination C:\\Windows\\Temp\\OOSU10.exe - C:\\Windows\\Temp\\OOSU10.exe C:\\Windows\\Temp\\ooshutup10.cfg /quiet" + C:\\Windows\\Temp\\OOSU10.exe C:\\Windows\\Temp\\ooshutup10.cfg /quiet" ] } } #> -#Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. -#Make sure to uncomment the sections you which to add. +# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. +# Make sure to uncomment the sections you which to add. #$Registry = @( -# #to add more repeat this separated by a comma +# # To add more repeat this separated by a comma # @{ # Path = "" # Name = "" @@ -301,7 +301,7 @@ Example: #) #$Service = @( -# #to add more repeat this separated by a comma +# # To add more repeat this separated by a comma # @{ # Name = "" # StartupType = "" @@ -310,7 +310,7 @@ Example: #) #$ScheduledTask = @( -# #to add more repeat this separated by a comma +# # To add more repeat this separated by a comma # @{ # Name = "" # State = "" @@ -323,11 +323,11 @@ Example: #) #$InvokeScript = @( -# "" +# "" #) #$UndoScript = @( -# "" +# "" #) $NameofButton = "WPF" + "" @@ -335,7 +335,7 @@ $NameofButton = "WPF" + "" $ButtonToAdd = New-Object psobject $jsonfile = Get-Content ./config/tweaks.json | ConvertFrom-Json -#remove if already exists +# Remove if already exists if($jsonfile.$NameofButton){ $jsonfile.psobject.Properties.remove($NameofButton) } @@ -375,10 +375,10 @@ Example: "Primary": "1.1.1.1", "Secondary": "1.0.0.1" } -} +} #> -#Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. +# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request. $NameofProvider = "" -replace " ","_" $IPAddress = @{ @@ -389,7 +389,7 @@ $IPAddress = @{ $ButtonToAdd = New-Object psobject $jsonfile = Get-Content ./config/dns.json | ConvertFrom-Json -#remove if already exists +# Remove if already exists if($jsonfile.$NameofProvider){ $jsonfile.psobject.Properties.remove($NameofProvider) } diff --git a/config/tweaks.json b/config/tweaks.json index e0056958..817bde10 100644 --- a/config/tweaks.json +++ b/config/tweaks.json @@ -1556,6 +1556,26 @@ "Name": "Microsoft\\Windows\\Windows Error Reporting\\QueueReporting", "State": "Disabled", "OriginalState": "Enabled" + }, + { + "Name": "Microsoft\\Windows\\Application Experience\\MareBackup", + "State": "Disabled", + "OriginalState": "Enabled" + }, + { + "Name": "Microsoft\\Windows\\Application Experience\\StartupAppTask", + "State": "Disabled", + "OriginalState": "Enabled" + }, + { + "Name": "Microsoft\\Windows\\Application Experience\\PcaPatchDbTask", + "State": "Disabled", + "OriginalState": "Enabled" + }, + { + "Name": "Microsoft\\Windows\\Maps\\MapsUpdateTask", + "State": "Disabled", + "OriginalState": "Enabled" } ], "registry": [ @@ -1842,7 +1862,8 @@ } ], "InvokeScript": [ - "bcdedit /set `{current`} bootmenupolicy Legacy | Out-Null + " + bcdedit /set `{current`} bootmenupolicy Legacy | Out-Null If ((get-ItemProperty -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\" -Name CurrentBuild).CurrentBuild -lt 22557) { $taskmgr = Start-Process -WindowStyle Hidden -FilePath taskmgr.exe -PassThru Do { @@ -1853,7 +1874,7 @@ $preferences.Preferences[28] = 0 Set-ItemProperty -Path \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\TaskManager\" -Name \"Preferences\" -Type Binary -Value $preferences.Preferences } - Remove-Item -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\NameSpace\\{0DB7E03F-FC29-4DC6-9020-FF41B59E513A}\" -Recurse -ErrorAction SilentlyContinue + Remove-Item -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\NameSpace\\{0DB7E03F-FC29-4DC6-9020-FF41B59E513A}\" -Recurse -ErrorAction SilentlyContinue # Group svchost.exe processes $ram = (Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1kb @@ -1864,6 +1885,9 @@ Remove-Item \"$autoLoggerDir\\AutoLogger-Diagtrack-Listener.etl\" } icacls $autoLoggerDir /deny SYSTEM:`(OI`)`(CI`)F | Out-Null + + # Disable Defender Auto Sample Submission + Set-MpPreference -SubmitSamplesConsent 2 -ErrorAction SilentlyContinue | Out-Null " ] }, @@ -1910,84 +1934,84 @@ "WPFMiscTweaksDisplay": { "registry": [ { - "path": "HKCU:\\Control Panel\\Desktop", + "Path": "HKCU:\\Control Panel\\Desktop", "OriginalValue": "1", "Name": "DragFullWindows", "Value": "0", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Desktop", + "Path": "HKCU:\\Control Panel\\Desktop", "OriginalValue": "1", "Name": "MenuShowDelay", "Value": "200", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Desktop\\WindowMetrics", + "Path": "HKCU:\\Control Panel\\Desktop\\WindowMetrics", "OriginalValue": "1", "Name": "MinAnimate", "Value": "0", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Keyboard", + "Path": "HKCU:\\Control Panel\\Keyboard", "OriginalValue": "1", "Name": "KeyboardDelay", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", "OriginalValue": "1", "Name": "ListviewAlphaSelect", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", "OriginalValue": "1", "Name": "ListviewShadow", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", "OriginalValue": "1", "Name": "TaskbarAnimations", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects", "OriginalValue": "1", "Name": "VisualFXSetting", "Value": "3", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\DWM", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\DWM", "OriginalValue": "1", "Name": "EnableAeroPeek", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", "OriginalValue": "1", "Name": "TaskbarMn", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", "OriginalValue": "1", "Name": "TaskbarDa", "Value": "0", "Type": "DWord" }, { - "path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", "OriginalValue": "1", "Name": "ShowTaskViewButton", "Value": "0", @@ -2089,26 +2113,26 @@ " $TeamsPath = [System.IO.Path]::Combine($env:LOCALAPPDATA, 'Microsoft', 'Teams') $TeamsUpdateExePath = [System.IO.Path]::Combine($TeamsPath, 'Update.exe') - + Write-Host \"Stopping Teams process...\" Stop-Process -Name \"*teams*\" -Force -ErrorAction SilentlyContinue - + Write-Host \"Uninstalling Teams from AppData\\Microsoft\\Teams\" if ([System.IO.File]::Exists($TeamsUpdateExePath)) { # Uninstall app $proc = Start-Process $TeamsUpdateExePath \"-uninstall -s\" -PassThru $proc.WaitForExit() } - + Write-Host \"Removing Teams AppxPackage...\" Get-AppxPackage \"*Teams*\" | Remove-AppxPackage -ErrorAction SilentlyContinue Get-AppxPackage \"*Teams*\" -AllUsers | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue - + Write-Host \"Deleting Teams directory\" if ([System.IO.Directory]::Exists($TeamsPath)) { Remove-Item $TeamsPath -Force -Recurse -ErrorAction SilentlyContinue } - + Write-Host \"Deleting Teams uninstall registry key\" # Uninstall from Uninstall registry key UninstallString $us = (Get-ChildItem -Path HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall, HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall | Get-ItemProperty | Where-Object { $_.DisplayName -like '*Teams*'}).UninstallString @@ -2133,7 +2157,7 @@ "WPFEssTweaksStorage": { "InvokeScript": [ "Remove-Item -Path \"HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\StorageSense\\Parameters\\StoragePolicy\" -Recurse -ErrorAction SilentlyContinue" - ], + ], "UndoScript": [ "New-Item -Path \"HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\StorageSense\\Parameters\\StoragePolicy\" | Out-Null " @@ -2142,7 +2166,7 @@ "WPFMiscTweaksLapNum": { "Registry": [ { - "path": "HKU:\\.DEFAULT\\Control Panel\\Keyboard", + "Path": "HKU:\\.DEFAULT\\Control Panel\\Keyboard", "OriginalValue": "1", "Name": "InitialKeyboardIndicators", "Value": "0", @@ -2153,7 +2177,7 @@ "WPFMiscTweaksNum": { "Registry": [ { - "path": "HKU:\\.DEFAULT\\Control Panel\\Keyboard", + "Path": "HKU:\\.DEFAULT\\Control Panel\\Keyboard", "OriginalValue": "1", "Name": "InitialKeyboardIndicators", "Value": "80000002", @@ -2163,10 +2187,10 @@ }, "WPFEssTweaksRemoveEdge": { "InvokeScript": [ - " + " #:: Standalone script by AveYo Source: https://raw.githubusercontent.com/AveYo/fox/main/Edge_Removal.bat - curl.exe -s \"https://raw.githubusercontent.com/AveYo/fox/main/Edge_Removal.bat\" -o $ENV:temp\\edgeremoval.bat + curl.exe -s \"https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/edgeremoval.bat\" -o $ENV:temp\\edgeremoval.bat Start-Process $ENV:temp\\edgeremoval.bat " @@ -2181,7 +2205,7 @@ "WPFEssTweaksRemoveOnedrive": { "InvokeScript": [ " - + Write-Host \"Kill OneDrive process\" taskkill.exe /F /IM \"OneDrive.exe\" taskkill.exe /F /IM \"explorer.exe\" @@ -2295,7 +2319,7 @@ "WPFMiscTweaksDisableUAC": { "registry": [ { - "path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", + "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", "OriginalValue": "5", "Name": "ConsentPromptBehaviorAdmin", "Value": "0", @@ -2306,21 +2330,21 @@ "WPFMiscTweaksDisableMouseAcceleration": { "registry": [ { - "path": "HKCU:\\Control Panel\\Mouse", + "Path": "HKCU:\\Control Panel\\Mouse", "OriginalValue": "1", "Name": "MouseSpeed", "Value": "0", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Mouse", + "Path": "HKCU:\\Control Panel\\Mouse", "OriginalValue": "6", "Name": "MouseThreshold1", "Value": "0", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Mouse", + "Path": "HKCU:\\Control Panel\\Mouse", "OriginalValue": "10", "Name": "MouseThreshold2", "Value": "0", @@ -2331,21 +2355,21 @@ "WPFMiscTweaksEnableMouseAcceleration": { "registry": [ { - "path": "HKCU:\\Control Panel\\Mouse", + "Path": "HKCU:\\Control Panel\\Mouse", "OriginalValue": "1", "Name": "MouseSpeed", "Value": "1", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Mouse", + "Path": "HKCU:\\Control Panel\\Mouse", "OriginalValue": "6", "Name": "MouseThreshold1", "Value": "6", "Type": "String" }, { - "path": "HKCU:\\Control Panel\\Mouse", + "Path": "HKCU:\\Control Panel\\Mouse", "OriginalValue": "10", "Name": "MouseThreshold2", "Value": "10", @@ -2356,7 +2380,7 @@ "WPFMiscTweaksEnableVerboselogon": { "registry": [ { - "path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\system", + "Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\system", "OriginalValue": "0", "Name": "VerboseStatus", "Value": "1", diff --git a/edgeremoval.bat b/edgeremoval.bat new file mode 100644 index 00000000..b950e873 --- /dev/null +++ b/edgeremoval.bat @@ -0,0 +1,236 @@ +@(set "0=%~f0"^)#) & powershell -nop -c iex([io.file]::ReadAllText($env:0)) & exit /b +#:: made by AveYo source: https://raw.githubusercontent.com/AveYo/fox/main/Edge_Removal.bat +sp 'HKCU:\Volatile Environment' 'Edge_Removal' @' + +$also_remove_webview = 0 + +$host.ui.RawUI.WindowTitle = 'Edge Removal - AveYo, 2023.09.09' +$remove_win32 = @("Microsoft Edge","Microsoft Edge Update"); $remove_appx = @("MicrosoftEdge"); $skip = @() # @("DevTools") +if ($also_remove_webview -eq 1) {$remove_win32 += "Microsoft EdgeWebView"; $remove_appx += "WebExperience","Win32WebViewHost"} + +## 1 bonus! enter into powershell console: firefox / edge / webview to install a browser / reinstall edge or webview after removal +function global:firefox { $url = 'https://download.mozilla.org/?product=firefox-stub' + $setup = "$((new-object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path)\Firefox Installer.exe" + write-host $url; Invoke-WebRequest $url -OutFile $setup; start $setup +} +function global:edge { $url = 'https://go.microsoft.com/fwlink/?linkid=2108834&Channel=Stable&language=en' + $setup = "$((new-object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path)\MicrosoftEdgeSetup.exe" + write-host $url; Invoke-WebRequest $url -OutFile $setup; prepare_edge; start $setup +} +function global:webview { $url = 'https://go.microsoft.com/fwlink/p/?LinkId=2124703' + $setup = "$((new-object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path)\MicrosoftEdgeWebview2Setup.exe" + write-host $url; Invoke-WebRequest $url -OutFile $setup; prepare_webview; start $setup +} +## helper for set-itemproperty remove-itemproperty new-item remove-item with auto test-path +function global:sp_test_path { if (test-path $args[0]) {Microsoft.PowerShell.Management\Set-ItemProperty @args} else { + Microsoft.PowerShell.Management\New-Item $args[0] -force -ea 0 >''; Microsoft.PowerShell.Management\Set-ItemProperty @args} } +function global:rp_test_path { if (test-path $args[0]) {Microsoft.PowerShell.Management\Remove-ItemProperty @args} } +function global:ni_test_path { if (-not (test-path $args[0])) {Microsoft.PowerShell.Management\New-Item @args} } +function global:ri_test_path { if (test-path $args[0]) {Microsoft.PowerShell.Management\Remove-Item @args} } +foreach ($f in 'sp','rp','ni','ri') {set-alias -Name $f -Value "${f}_test_path" -Scope Local -Option AllScope -force -ea 0} +## helper for edge reinstall - remove bundled OpenWebSearch redirector and edgeupdate policies +function global:prepare_edge { + foreach ($f in 'ni','ri','sp','rp') {set-alias -Name $f -Value "${f}_test_path" -Scope Local -Option AllScope -force -ea 0} + $MS=($env:ProgramFiles,${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem]+'\Microsoft\Edge\Application\msedge.exe' + ri "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\msedge.exe" -recurse -force -ea 0 + ri "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ie_to_edge_stub.exe" -recurse -force -ea 0 + ri 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\microsoft-edge' -recurse -force -ea 0 + ri 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\MSEdgeHTM' -recurse -force -ea 0 + ni "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -force -ea 0 >'' + sp "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" '(Default)' "`"$MS`" --single-argument %%1" -force -ea 0 + ni "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -force -ea 0 >'' + sp "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" '(Default)' "`"$MS`" --single-argument %%1" -force -ea 0 + foreach ($p in 'HKLM:\SOFTWARE\Policies','HKLM:\SOFTWARE','HKLM:\SOFTWARE\WOW6432Node') { + rp "$p\Microsoft\EdgeUpdate" 'InstallDefault' -force -ea 0 + rp "$p\Microsoft\EdgeUpdate" 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' -force -ea 0 + rp "$p\Microsoft\EdgeUpdate" 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' -force -ea 0 + } + $edgeupdate='Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' + $webvupdate='Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' + $on_actions='on-os-upgrade','on-logon','on-logon-autolaunch','on-logon-startup-boost' + foreach ($p in 'HKLM:\SOFTWARE','HKLM:\SOFTWARE\Wow6432Node') { foreach ($launch in $on_actions) { + ri "$p\$edgeupdate\Commands\$launch" -force -ea 0; ri "$p\$webvupdate\Commands\$launch" -force -ea 0 + }} +} +## helper for webview reinstall - restore webexperience (widgets) if available +function global:prepare_webview { + $cfg = @{Register=$true; ForceApplicationShutdown=$true; ForceUpdateFromAnyVersion=$true; DisableDevelopmentMode=$true} + dir "$env:ProgramFiles\WindowsApps\MicrosoftWindows.Client.WebExperience*\AppxManifest.xml" -rec -ea 0 | Add-AppxPackage @cfg + dir "$env:SystemRoot\SystemApps\Microsoft.Win32WebViewHost*\AppxManifest.xml" -rec -ea 0 | Add-AppxPackage @cfg + kill -name explorer -ea 0; if ((get-process -name 'explorer' -ea 0) -eq $null) {start explorer} +} + +## 2 enable admin privileges +$D1=[uri].module.gettype('System.Diagnostics.Process')."GetM`ethods"(42) |where {$_.Name -eq 'SetPrivilege'} #`:no-ev-warn +'SeSecurityPrivilege','SeTakeOwnershipPrivilege','SeBackupPrivilege','SeRestorePrivilege'|foreach {$D1.Invoke($null, @("$_",2))} + +## 3 shut edge & webview clone stuff down and gather install paths +$shut = 'explorer','Widgets','widgetservice','msedgewebview2','MicrosoftEdge*','chredge','msedge','edge' +$shut+= 'msteams','msfamily','WebViewHost','Clipchamp' +cd $env:systemdrive; taskkill /im explorer.exe /f 2>&1 >''; foreach ($p in $shut) {kill -name $p -force -ea 0} +prepare_edge +## clear win32 uninstall block +foreach ($hk in 'HKCU:','HKLM:') { foreach ($wow in '','\Wow6432Node') { foreach ($i in $remove_win32) { + rp "$hk\SOFTWARE${wow}\Microsoft\Windows\CurrentVersion\Uninstall\$i" 'NoRemove' -force -ea 0 + ni "$hk\SOFTWARE${wow}\Microsoft\EdgeUpdateDev" -force >'' + sp "$hk\SOFTWARE${wow}\Microsoft\EdgeUpdateDev" 'AllowUninstall' 1 -type Dword -force +}}} +## find all Edge setup.exe and gather BHO paths for OpenWebSearch / MSEdgeRedirect usage +$edges = @(); $bho = @(); 'LocalApplicationData','ProgramFilesX86','ProgramFiles' |foreach { + $folder = [Environment]::GetFolderPath($_); $bho += dir "$folder\Microsoft\Edge*\ie_to_edge_stub.exe" -rec -ea 0 + if ($also_remove_webview -eq 1) {$edges += dir "$folder\Microsoft\Edge*\setup.exe" -rec -ea 0 |where {$_ -like '*EdgeWebView*'}} + $edges += dir "$folder\Microsoft\Edge*\setup.exe" -rec -ea 0 |where {$_ -notlike '*EdgeWebView*'} +} +## use dedicated C:\Scripts path to save OpenWebSearch (due to Sigma rules FUD) +$DIR = "$env:SystemDrive\Scripts"; mkdir $DIR -ea 0 >'' +## export OpenWebSearch innovative redirector - used by MSEdgeRedirect as well +foreach ($b in $bho) { if (test-path $b) { try {copy $b "$DIR\ie_to_edge_stub.exe" -force -ea 0} catch{} } } + +## 4 remove found *Edge* appx packages with unblock tricks +$provisioned = get-appxprovisionedpackage -online; $appxpackage = get-appxpackage -allusers; $eol = @() +$store = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore' +$users = @('S-1-5-18'); if (test-path $store) {$users += $((dir $store -ea 0 |where {$_ -like '*S-1-5-21*'}).PSChildName)} +foreach ($choice in $remove_appx) { if ('' -eq $choice.Trim()) {continue} + foreach ($appx in $($provisioned |where {$_.PackageName -like "*$choice*"})) { + $next = !1; foreach ($no in $skip) {if ($appx.PackageName -like "*$no*") {$next = !0}} ; if ($next) {continue} + $PackageName = $appx.PackageName; $PackageFamilyName = ($appxpackage |where {$_.Name -eq $appx.DisplayName}).PackageFamilyName + ni "$store\Deprovisioned\$PackageFamilyName" -force >''; $PackageFamilyName + foreach ($sid in $users) {ni "$store\EndOfLife\$sid\$PackageName" -force >''} ; $eol += $PackageName + dism /online /set-nonremovableapppolicy /packagefamily:$PackageFamilyName /nonremovable:0 >'' + remove-appxprovisionedpackage -packagename $PackageName -online -allusers >'' + } + foreach ($appx in $($appxpackage |where {$_.PackageFullName -like "*$choice*"})) { + $next = !1; foreach ($no in $skip) {if ($appx.PackageFullName -like "*$no*") {$next = !0}} ; if ($next) {continue} + $PackageFullName = $appx.PackageFullName; + ni "$store\Deprovisioned\$appx.PackageFamilyName" -force >''; $PackageFullName + foreach ($sid in $users) {ni "$store\EndOfLife\$sid\$PackageFullName" -force >''} ; $eol += $PackageFullName + dism /online /set-nonremovableapppolicy /packagefamily:$PackageFamilyName /nonremovable:0 >'' + remove-appxpackage -package $PackageFullName -allusers >'' + } +} + +## 5 run found *Edge* setup.exe with uninstall args and wait in-between +foreach ($setup in $edges) { if (test-path $setup) { + if ($setup -like '*EdgeWebView*') {$target = "--msedgewebview"} else {$target = "--msedge"} + $removal = "--uninstall $target --system-level --verbose-logging --force-uninstall" + try {write-host $setup $removal; start -wait $setup -args $removal} catch {} + do {sleep 3} while ((get-process -name 'setup','MicrosoftEdge*' -ea 0).Path -like '*\Microsoft\Edge*') +}} + +## 6 extra cleanup +foreach ($PF in $env:ProgramFiles,${env:ProgramFiles(x86)}) { if (test-path "$PF\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe") { + write-host "$PF\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe /uninstall" + start -wait "$PF\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" -args '/uninstall' + do {sleep 3} while ((get-process -name 'setup','MicrosoftEdge*' -ea 0).Path -like '*\Microsoft\Edge*') + if ($also_remove_webview -eq 1) { foreach ($hk in 'HKCU:','HKLM:') { foreach ($wow in '','\Wow6432Node') { + ri "$hk\SOFTWARE${wow}\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update" -rec -force -ea 0 }} + ri "$PF\Microsoft\EdgeUpdate" -rec -force -ea 0; Unregister-ScheduledTask -TaskName MicrosoftEdgeUpdate* -Confirm:$false -ea 0 + } +}} +$appdata = $([Environment]::GetFolderPath('ApplicationData')) +ri "$appdata\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Tombstones\Microsoft Edge.lnk" -force +ri "$appdata\Microsoft\Internet Explorer\Quick Launch\Microsoft Edge.lnk" -force + +## undo eol unblock trick to prevent latest cumulative update (LCU) failing +foreach ($sid in $users) { foreach ($PackageName in $eol) {ri "$store\EndOfLife\$sid\$PackageName" -force >''} } + +## set (almost) useless policies to prevent unsolicited reinstalls +foreach ($p in 'HKLM:\SOFTWARE\Policies','HKLM:\SOFTWARE','HKLM:\SOFTWARE\WOW6432Node') { + ni "$p\Microsoft\EdgeUpdate" -force >'' + sp "$p\Microsoft\EdgeUpdate" 'InstallDefault' 0 -type Dword -force + sp "$p\Microsoft\EdgeUpdate" 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' 0 -type Dword -force + sp "$p\Microsoft\EdgeUpdate" 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' 1 -type Dword -force + sp "$p\Microsoft\EdgeUpdate" 'DoNotUpdateToEdgeWithChromium' 1 -type Dword -force +} +$edgeupdate='Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' +$webvupdate='Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' +$on_actions='on-os-upgrade','on-logon','on-logon-autolaunch','on-logon-startup-boost' +foreach ($p in 'HKLM:\SOFTWARE','HKLM:\SOFTWARE\Wow6432Node') { foreach ($launch in $on_actions) { + ni "$p\$edgeupdate\Commands\$launch" -force >''; sp "$p\$edgeupdate\Commands\$launch" 'CommandLine' 'systray.exe' -force + ni "$p\$webvupdate\Commands\$launch" -force >''; sp "$p\$webvupdate\Commands\$launch" 'CommandLine' 'systray.exe' -force +}} + +## 7 add bundled OpenWebSearch script to redirect microsoft-edge: anti-competitive links to the default browser +$MSEP = ($env:ProgramFiles,${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem] + '\Microsoft\Edge\Application' +$IFEO = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options' +$MIN = ('--headless','--width 1 --height 1')[([environment]::OSVersion.Version.Build) -gt 25179] +$CMD = "$env:systemroot\system32\conhost.exe $MIN" # AveYo: minimize prompt - see Terminal issue #13914 +ni "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -force >'' +sp "HKLM:\SOFTWARE\Classes\microsoft-edge" '(Default)' 'URL:microsoft-edge' -force +sp "HKLM:\SOFTWARE\Classes\microsoft-edge" 'URL Protocol' '' -force +sp "HKLM:\SOFTWARE\Classes\microsoft-edge" 'NoOpenWith' '' -force +sp "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" '(Default)' "`"$DIR\ie_to_edge_stub.exe`" %1" -force +ni "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -force >'' +sp "HKLM:\SOFTWARE\Classes\MSEdgeHTM" 'NoOpenWith' '' -force +sp "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" '(Default)' "`"$DIR\ie_to_edge_stub.exe`" %1" -force +ni "$IFEO\ie_to_edge_stub.exe\0" -force >'' +sp "$IFEO\ie_to_edge_stub.exe" 'UseFilter' 1 -type Dword -force +sp "$IFEO\ie_to_edge_stub.exe\0" 'FilterFullPath' "$DIR\ie_to_edge_stub.exe" -force +sp "$IFEO\ie_to_edge_stub.exe\0" 'Debugger' "$CMD $DIR\OpenWebSearch.cmd" -force +ni "$IFEO\msedge.exe\0" -force >'' +sp "$IFEO\msedge.exe" 'UseFilter' 1 -type Dword -force +sp "$IFEO\msedge.exe\0" 'FilterFullPath' "$MSEP\msedge.exe" -force +sp "$IFEO\msedge.exe\0" 'Debugger' "$CMD $DIR\OpenWebSearch.cmd" -force + +$OpenWebSearch = @$ +@title OpenWebSearch Redux & echo off & set ?= open start menu web search, widgets links or help in your chosen browser - by AveYo +for /f %%E in ('"prompt $E$S& for %%e in (1) do rem"') do echo;%%E[2t 2>nul & rem AveYo: minimize prompt +call :reg_var "HKCU\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" ProgID ProgID +if /i "%ProgID%" equ "MSEdgeHTM" echo;Default browser is set to Edge! Change it or remove OpenWebSearch script. & pause & exit /b +call :reg_var "HKCR\%ProgID%\shell\open\command" "" Browser +set Choice=& for %%. in (%Browser%) do if not defined Choice set "Choice=%%~." +call :reg_var "HKCR\MSEdgeMHT\shell\open\command" "" FallBack +set "Edge=" & for %%. in (%FallBack%) do if not defined Edge set "Edge=%%~." +set "URI=" & set "URL=" & set "NOOP=" & set "PassTrough=%Edge:msedge=edge%" +set "CLI=%CMDCMDLINE:"=``% " +if defined CLI set "CLI=%CLI:*ie_to_edge_stub.exe`` =%" +if defined CLI set "CLI=%CLI:*ie_to_edge_stub.exe =%" +if defined CLI set "CLI=%CLI:*msedge.exe`` =%" +if defined CLI set "CLI=%CLI:*msedge.exe =%" +set "FIX=%CLI:~-1%" +if defined CLI if "%FIX%"==" " set "CLI=%CLI:~0,-1%" +if defined CLI set "RED=%CLI:microsoft-edge=%" +if defined CLI set "URL=%CLI:http=%" +if defined CLI set "ARG=%CLI:``="%" +if "%CLI%" equ "%RED%" (set NOOP=1) else if "%CLI%" equ "%URL%" (set NOOP=1) +if defined NOOP if exist "%PassTrough%" start "" "%PassTrough%" %ARG% +if defined NOOP exit /b +set "URL=%CLI:*microsoft-edge=%" +set "URL=http%URL:*http=%" +set "FIX=%URL:~-2%" +if defined URL if "%FIX%"=="``" set "URL=%URL:~0,-2%" +call :dec_url +start "" "%Choice%" "%URL%" +exit + +:reg_var [USAGE] call :reg_var "HKCU\Volatile Environment" value-or-"" variable [extra options] +set {var}=& set {reg}=reg query "%~1" /v %2 /z /se "," /f /e& if %2=="" set {reg}=reg query "%~1" /ve /z /se "," /f /e +for /f "skip=2 tokens=* delims=" %%V in ('%{reg}% %4 %5 %6 %7 %8 %9 2^>nul') do if not defined {var} set "{var}=%%V" +if not defined {var} (set {reg}=& set "%~3="& exit /b) else if %2=="" set "{var}=%{var}:*) =%"& rem AveYo: v3 +if not defined {var} (set {reg}=& set "%~3="& exit /b) else set {reg}=& set "%~3=%{var}:*) =%"& set {var}=& exit /b + +:dec_url brute url percent decoding by AveYo +set ".=%URL:!=}%"&setlocal enabledelayedexpansion& rem brute url percent decoding +set ".=!.:%%={!" &set ".=!.:{3A=:!" &set ".=!.:{2F=/!" &set ".=!.:{3F=?!" &set ".=!.:{23=#!" &set ".=!.:{5B=[!" &set ".=!.:{5D=]!" +set ".=!.:{40=@!"&set ".=!.:{21=}!" &set ".=!.:{24=$!" &set ".=!.:{26=&!" &set ".=!.:{27='!" &set ".=!.:{28=(!" &set ".=!.:{29=)!" +set ".=!.:{2A=*!"&set ".=!.:{2B=+!" &set ".=!.:{2C=,!" &set ".=!.:{3B=;!" &set ".=!.:{3D==!" &set ".=!.:{25=%%!"&set ".=!.:{20= !" +set ".=!.:{=%%!" &rem set ",=!.:%%=!" & if "!,!" neq "!.!" endlocal& set "URL=%.:}=!%" & call :dec_url +endlocal& set "URL=%.:}=!%" & exit /b +rem done + +$@ +[io.file]::WriteAllText("$DIR\OpenWebSearch.cmd", $OpenWebSearch) + +## 8 done +$done = gp 'Registry::HKEY_Users\S-1-5-21*\Volatile*' Edge_Removal -ea 0; if ($done) {rp $done.PSPath Edge_Removal -force -ea 0} +if ((get-process -name 'explorer' -ea 0) -eq $null) {start explorer} + +## 9 bonus enter into powershell console: firefox / edge / webview to install a browser / reinstall edge or webview after removal +${.} = [char]27; $firefox = "${.}[38;2;255;165;0m firefox"; $edge = "${.}[94m edge${.}[97m"; $webview = "${.}[94mwebview ${.}[97m" +write-host "`n${.}[40;32m EDGE REMOVED! ${.}[97m -GET-ANOTHER-BROWSER? ENTER:$firefox ${.}[97m -REINSTALL? ENTER:$edge / $webview" + +## 0 ask to run script as admin +'@.replace("$@","'@").replace("@$","@'") -force -ea 0; $code='gp ''Registry::HKEY_Users\S-1-5-21*\Volatile*'' Edge_Removal -ea 0' +start powershell -args "-nop -noe -c & {iex(($code)[0].Edge_Removal)}" -verb runas +$_Press_Enter +#:: diff --git a/edgeremoval.ps1 b/edgeremoval.ps1 new file mode 100644 index 00000000..3f698087 --- /dev/null +++ b/edgeremoval.ps1 @@ -0,0 +1,466 @@ +# Script Metadata +# Created by AveYo, source: https://raw.githubusercontent.com/AveYo/fox/main/Edge_Removal.bat +# Powershell Conversion and Refactor done by Chris Titus Tech + +# Initial Configuration +$host.ui.RawUI.WindowTitle = 'Edge Removal - Chris Titus Tech 2023.05.10' +$remove_win32 = @("Microsoft Edge", "Microsoft Edge Update") +$remove_appx = @("MicrosoftEdge") +$skip = @() # Optional: @("DevTools") + +$also_remove_webview = 0 +if ($also_remove_webview -eq 1) { + $remove_win32 += "Microsoft EdgeWebView" + $remove_appx += "WebExperience", "Win32WebViewHost" +} + +# Administrative Privileges Check + +# Get the 'SetPrivilege' method from System.Diagnostics.Process type +$setPrivilegeMethod = [System.Diagnostics.Process].GetMethod('SetPrivilege', [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Static) + +# List of privileges to set +$privileges = @( + 'SeSecurityPrivilege', + 'SeTakeOwnershipPrivilege', + 'SeBackupPrivilege', + 'SeRestorePrivilege' +) + +# Invoke the method for each privilege +foreach ($privilege in $privileges) { + $setPrivilegeMethod.Invoke($null, @($privilege, 2)) +} + +# Edge Removal Procedures + +# Define processes to shut down +$processesToShutdown = @( + 'explorer', 'Widgets', 'widgetservice', 'msedgewebview2', 'MicrosoftEdge*', 'chredge', + 'msedge', 'edge', 'msteams', 'msfamily', 'WebViewHost', 'Clipchamp' +) + +# Kill explorer process +Stop-Process -Name "explorer" -Force -ErrorAction SilentlyContinue + +# Kill the processes from the list +$processesToShutdown | ForEach-Object { + Stop-Process -Name $_ -Force -ErrorAction SilentlyContinue +} + +# Set path for Edge executable +$MS = ($env:ProgramFiles, ${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem] + '\Microsoft\Edge\Application\msedge.exe' + +# Clean up certain registry entries +Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\msedge.exe" -Recurse -ErrorAction SilentlyContinue +Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ie_to_edge_stub.exe" -Recurse -ErrorAction SilentlyContinue +Remove-Item -Path 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\microsoft-edge' -Recurse -ErrorAction SilentlyContinue +Remove-Item -Path 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\MSEdgeHTM' -Recurse -ErrorAction SilentlyContinue + +# Create new registry entries +New-Item -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Force -ErrorAction SilentlyContinue +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Name '(Default)' -Value "`"$MS`" --single-argument %%1" -Force -ErrorAction SilentlyContinue + +New-Item -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Force -ErrorAction SilentlyContinue +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Name '(Default)' -Value "`"$MS`" --single-argument %%1" -Force -ErrorAction SilentlyContinue + +# Remove certain registry properties +$registryPaths = @('HKLM:\SOFTWARE\Policies', 'HKLM:\SOFTWARE', 'HKLM:\SOFTWARE\WOW6432Node') +$edgeProperties = @('InstallDefault', 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}', 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}') +foreach ($path in $registryPaths) { + foreach ($prop in $edgeProperties) { + Remove-ItemProperty -Path "$path\Microsoft\EdgeUpdate" -Name $prop -Force -ErrorAction SilentlyContinue + } +} + +$edgeupdate = 'Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' +$webvupdate = 'Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' +$on_actions = @('on-os-upgrade', 'on-logon', 'on-logon-autolaunch', 'on-logon-startup-boost') +$registryBases = @('HKLM:\SOFTWARE', 'HKLM:\SOFTWARE\Wow6432Node') +foreach ($base in $registryBases) { + foreach ($launch in $on_actions) { + Remove-Item -Path "$base\$edgeupdate\Commands\$launch" -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$base\$webvupdate\Commands\$launch" -Force -ErrorAction SilentlyContinue + } +} + +# Clear specific registry keys +$registryPaths = @('HKCU:', 'HKLM:') +$nodes = @('', '\Wow6432Node') +foreach ($regPath in $registryPaths) { + foreach ($node in $nodes) { + foreach ($i in $remove_win32) { + Remove-ItemProperty -Path "$regPath\SOFTWARE${node}\Microsoft\Windows\CurrentVersion\Uninstall\$i" -Name 'NoRemove' -Force -ErrorAction SilentlyContinue + New-Item -Path "$regPath\SOFTWARE${node}\Microsoft\EdgeUpdateDev" -Force | Out-Null + Set-ItemProperty -Path "$regPath\SOFTWARE${node}\Microsoft\EdgeUpdateDev" -Name 'AllowUninstall' -Value 1 -Type Dword -Force + } + } +} + +# Locate setup.exe and ie_to_edge_stub.exe +$foldersToSearch = @('LocalApplicationData', 'ProgramFilesX86', 'ProgramFiles') | ForEach-Object { + [Environment]::GetFolderPath($_) +} + +$edges = @() +$bhoFiles = @() + +foreach ($folder in $foldersToSearch) { + $bhoFiles += Get-ChildItem -Path "$folder\Microsoft\Edge*\ie_to_edge_stub.exe" -Recurse -ErrorAction SilentlyContinue + + $edges += Get-ChildItem -Path "$folder\Microsoft\Edge*\setup.exe" -Recurse -ErrorAction SilentlyContinue | + Where-Object { $_.FullName -notlike '*EdgeWebView*' } +} + +# Create directory and copy ie_to_edge_stub.exe to it +$destinationDir = "$env:SystemDrive\Scripts" +New-Item -Path $destinationDir -ItemType Directory -ErrorAction SilentlyContinue | Out-Null + +foreach ($bhoFile in $bhoFiles) { + if (Test-Path $bhoFile) { + try { + Copy-Item -Path $bhoFile -Destination "$destinationDir\ie_to_edge_stub.exe" -Force + } catch { } + } +} + +## Work on Appx Removals + +# Retrieve AppX provisioned packages and all AppX packages +$provisioned = Get-AppxProvisionedPackage -Online +$appxpackage = Get-AppxPackage -AllUsers + +# Initialize empty array for EndOfLife packages +$eol = @() + +# Define user SIDs and retrieve them from the registry +$store = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore' +$users = @('S-1-5-18') +if (Test-Path $store) { + $users += (Get-ChildItem $store -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -like '*S-1-5-21*' }).PSChildName +} + +# Process AppX packages for removal +foreach ($choice in $remove_appx) { + if ([string]::IsNullOrWhiteSpace($choice)) { continue } + + # Process provisioned packages + $provisioned | Where-Object { $_.PackageName -like "*$choice*" } | ForEach-Object { + if ($skip -Contains $_.PackageName) { return } + + $PackageName = $_.PackageName + $PackageFamilyName = ($appxpackage | Where-Object { $_.Name -eq $_.DisplayName }).PackageFamilyName + + # Add registry entries + New-Item -Path "$store\Deprovisioned\$PackageFamilyName" -Force -ErrorAction SilentlyContinue | Out-Null + $users | ForEach-Object { + New-Item -Path "$store\EndOfLife\$_\$PackageName" -Force -ErrorAction SilentlyContinue | Out-Null + } + $eol += $PackageName + + # Modify non-removable app policy and remove package + dism /online /set-nonremovableapppolicy /packagefamily:$PackageFamilyName /nonremovable:0 | Out-Null + Remove-AppxProvisionedPackage -PackageName $PackageName -Online -AllUsers | Out-Null + } + + # Process all AppX packages + $appxpackage | Where-Object { $_.PackageFullName -like "*$choice*" } | ForEach-Object { + if ($skip -Contains $_.PackageFullName) { return } + + $PackageFullName = $_.PackageFullName + + # Add registry entries + New-Item -Path "$store\Deprovisioned\$_.PackageFamilyName" -Force -ErrorAction SilentlyContinue | Out-Null + $users | ForEach-Object { + New-Item -Path "$store\EndOfLife\$_\$PackageFullName" -Force -ErrorAction SilentlyContinue | Out-Null + } + $eol += $PackageFullName + + # Modify non-removable app policy and remove package + dism /online /set-nonremovableapppolicy /packagefamily:$PackageFamilyName /nonremovable:0 | Out-Null + Remove-AppxPackage -Package $PackageFullName -AllUsers | Out-Null + } +} + +## Run Edge setup uninstaller + +foreach ($setup in $edges) { + if (Test-Path $setup) { + $target = if ($setup -like '*EdgeWebView*') { "--msedgewebview" } else { "--msedge" } + + $removalArgs = "--uninstall $target --system-level --verbose-logging --force-uninstall" + + Write-Host "$setup $removalArgs" + + try { + Start-Process -FilePath $setup -ArgumentList $removalArgs -Wait + } catch { + # You may want to add logging or other error handling here. + } + + while ((Get-Process -Name 'setup', 'MicrosoftEdge*' -ErrorAction SilentlyContinue).Path -like '*\Microsoft\Edge*') { + Start-Sleep -Seconds 3 + } + } +} + +## Cleanup + +# Define necessary paths and variables +$edgePaths = $env:ProgramFiles, ${env:ProgramFiles(x86)} +$appDataPath = [Environment]::GetFolderPath('ApplicationData') + +# Uninstall Microsoft Edge Update +foreach ($path in $edgePaths) { + $edgeUpdateExe = "$path\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" + if (Test-Path $edgeUpdateExe) { + Write-Host $edgeUpdateExe /uninstall + Start-Process -FilePath $edgeUpdateExe -ArgumentList '/uninstall' -Wait + while ((Get-Process -Name 'setup','MicrosoftEdge*' -ErrorAction SilentlyContinue).Path -like '*\Microsoft\Edge*') { + Start-Sleep -Seconds 3 + } + if ($also_remove_webview -eq 1) { + foreach ($regPath in 'HKCU:', 'HKLM:') { + foreach ($node in '', '\Wow6432Node') { + Remove-Item -Path "$regPath\SOFTWARE$node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update" -Recurse -Force -ErrorAction SilentlyContinue + } + } + Remove-Item -Path "$path\Microsoft\EdgeUpdate" -Recurse -Force -ErrorAction SilentlyContinue + Unregister-ScheduledTask -TaskName 'MicrosoftEdgeUpdate*' -Confirm:$false -ErrorAction SilentlyContinue + } + } +} + +# Remove Edge shortcuts +Remove-Item -Path "$appDataPath\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Tombstones\Microsoft Edge.lnk" -Force -ErrorAction SilentlyContinue +Remove-Item -Path "$appDataPath\Microsoft\Internet Explorer\Quick Launch\Microsoft Edge.lnk" -Force -ErrorAction SilentlyContinue + +# Revert settings related to Microsoft Edge +foreach ($sid in $users) { + foreach ($packageName in $eol) { + Remove-Item -Path "$store\EndOfLife\$sid\$packageName" -Force -ErrorAction SilentlyContinue + } +} + +# Set policies to prevent unsolicited reinstalls of Microsoft Edge +$registryPaths = @('HKLM:\SOFTWARE\Policies', 'HKLM:\SOFTWARE', 'HKLM:\SOFTWARE\WOW6432Node') +$edgeUpdatePolicies = @{ + 'InstallDefault' = 0; + 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' = 0; + 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' = 1; + 'DoNotUpdateToEdgeWithChromium' = 1; +} + +foreach ($path in $registryPaths) { + New-Item -Path "$path\Microsoft\EdgeUpdate" -Force -ErrorAction SilentlyContinue | Out-Null + foreach ($policy in $edgeUpdatePolicies.GetEnumerator()) { + Set-ItemProperty -Path "$path\Microsoft\EdgeUpdate" -Name $policy.Key -Value $policy.Value -Type Dword -Force + } +} + +$edgeUpdateActions = @('on-os-upgrade', 'on-logon', 'on-logon-autolaunch', 'on-logon-startup-boost') +$edgeUpdateClients = @( + 'Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}', + 'Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' +) +foreach ($client in $edgeUpdateClients) { + foreach ($action in $edgeUpdateActions) { + foreach ($regBase in 'HKLM:\SOFTWARE', 'HKLM:\SOFTWARE\Wow6432Node') { + $regPath = "$regBase\$client\Commands\$action" + New-Item -Path $regPath -Force -ErrorAction SilentlyContinue | Out-Null + Set-ItemProperty -Path $regPath -Name 'CommandLine' -Value 'systray.exe' -Force + } + } +} + +## Redirect Edge Shortcuts + +# Define Microsoft Edge Paths +$MSEP = ($env:ProgramFiles, ${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem] + '\Microsoft\Edge\Application' +$IFEO = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options' +$MIN = ('--headless', '--width 1 --height 1')[([environment]::OSVersion.Version.Build) -gt 25179] +$CMD = "$env:systemroot\system32\conhost.exe $MIN" +$DIR = "$env:SystemDrive\Scripts" + +# Setup Microsoft Edge Registry Entries +New-Item -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Force | Out-Null +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge" -Name '(Default)' -Value 'URL:microsoft-edge' -Force +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge" -Name 'URL Protocol' -Value '' -Force +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge" -Name 'NoOpenWith' -Value '' -Force +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Name '(Default)' -Value "`"$DIR\ie_to_edge_stub.exe`" %1" -Force + +# Setup MSEdgeHTM Registry Entries +New-Item -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Force | Out-Null +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM" -Name 'NoOpenWith' -Value '' -Force +Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Name '(Default)' -Value "`"$DIR\ie_to_edge_stub.exe`" %1" -Force + +# Setup Image File Execution Options for Edge and Edge WebView +$exeSettings = @( + @{ ExeName = 'ie_to_edge_stub.exe'; Debugger = "$CMD $DIR\OpenWebSearch.cmd"; FilterPath = "$DIR\ie_to_edge_stub.exe" }, + @{ ExeName = 'msedge.exe'; Debugger = "$CMD $DIR\OpenWebSearch.cmd"; FilterPath = "$MSEP\msedge.exe" } +) + +foreach ($setting in $exeSettings) { + New-Item -Path "$IFEO\$($setting.ExeName)\0" -Force | Out-Null + Set-ItemProperty -Path "$IFEO\$($setting.ExeName)" -Name 'UseFilter' -Value 1 -Type Dword -Force + Set-ItemProperty -Path "$IFEO\$($setting.ExeName)\0" -Name 'FilterFullPath' -Value $setting.FilterPath -Force + Set-ItemProperty -Path "$IFEO\$($setting.ExeName)\0" -Name 'Debugger' -Value $setting.Debugger -Force +} + +# Write OpenWebSearch Batch Script +$OpenWebSearch = @' +@echo off +@title OpenWebSearch Redux + +:: Minimize prompt +for /f %%E in ('"prompt $E$S & for %%e in (1) do rem"') do echo;%%E[2t >nul 2>&1 + +:: Get default browser from registry +call :get_registry_value "HKCU\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" ProgID DefaultBrowser +if not defined DefaultBrowser ( + echo Error: Failed to get default browser from registry. + pause + exit /b +) +if /i "%DefaultBrowser%" equ "MSEdgeHTM" ( + echo Error: Default browser is set to Edge! Change it or remove OpenWebSearch script. + pause + exit /b +) + +:: Get browser command line +call :get_registry_value "HKCR\%DefaultBrowser%\shell\open\command" "" BrowserCommand +if not defined BrowserCommand ( + echo Error: Failed to get browser command from registry. + pause + exit /b +) +set Browser=& for %%i in (%BrowserCommand%) do if not defined Browser set "Browser=%%~i" + +:: Set fallback for Edge +call :get_registry_value "HKCR\MSEdgeMHT\shell\open\command" "" FallBack +set EdgeCommand=& for %%i in (%FallBack%) do if not defined EdgeCommand set "EdgeCommand=%%~i" + +:: Parse command line arguments and check for redirect or noop conditions +set "URI=" & set "URL=" & set "NOOP=" & set "PassThrough=%EdgeCommand:msedge=edge%" +set "CommandLineArgs=%CMDCMDLINE:"=``% " +call :parse_arguments + +if defined NOOP ( + if not exist "%PassThrough%" ( + echo Error: PassThrough path doesn't exist. + pause + exit /b + ) + start "" "%PassThrough%" %ParsedArgs% + exit /b +) + +:: Decode URL +call :decode_url +if not defined URL ( + echo Error: Failed to decode URL. + pause + exit /b +) + +:: Open URL in default browser +start "" "%Browser%" "%URL%" +exit + +:: Functions + +:get_registry_value +setlocal + set regQuery=reg query "%~1" /v %2 /z /se "," /f /e + if "%~2" equ "" set regQuery=reg query "%~1" /ve /z /se "," /f /e + for /f "skip=2 tokens=* delims=" %%V in ('%regQuery% 2^>nul') do set "result=%%V" + if defined result (set "result=%result:*) =%") else (set "%~3=") + endlocal & set "%~3=%result%" +exit /b + +:decode_url + :: Brute URL percent decoding + setlocal enabledelayedexpansion + set "decoded=%URL:!=}%" + call :brute_decode + endlocal & set "URL=%decoded%" +exit /b + +:parse_arguments + :: Remove specific substrings from arguments + set "CommandLineArgs=%CommandLineArgs:*ie_to_edge_stub.exe`` =%" + set "CommandLineArgs=%CommandLineArgs:*ie_to_edge_stub.exe =%" + set "CommandLineArgs=%CommandLineArgs:*msedge.exe`` =%" + set "CommandLineArgs=%CommandLineArgs:*msedge.exe =%" + + :: Remove any trailing spaces + if "%CommandLineArgs:~-1%"==" " set "CommandLineArgs=%CommandLineArgs:~0,-1%" + + :: Check if arguments are a redirect or URL + set "RedirectArg=%CommandLineArgs:microsoft-edge=%" + set "UrlArg=%CommandLineArgs:http=%" + set "ParsedArgs=%CommandLineArgs:``="%" + + :: Set NOOP flag if no changes to arguments + if "%CommandLineArgs%" equ "%RedirectArg%" (set NOOP=1) else if "%CommandLineArgs%" equ "%UrlArg%" (set NOOP=1) + + :: Extract URL if present + if not defined NOOP ( + set "URL=%CommandLineArgs:*microsoft-edge=%" + set "URL=http%URL:*http=%" + if "%URL:~-2%"=="``" set "URL=%URL:~0,-2%" + ) +exit /b + + +:brute_decode + :: Brute force URL percent decoding + + set "decoded=%decoded:%%20= %" + set "decoded=%decoded:%%21=!!" + set "decoded=%decoded:%%22="%"" + set "decoded=%decoded:%%23=#%" + set "decoded=%decoded:%%24=$%" + set "decoded=%decoded:%%25=%%%" + set "decoded=%decoded:%%26=&%" + set "decoded=%decoded:%%27='%" + set "decoded=%decoded:%%28=(%" + set "decoded=%decoded:%%29=)%" + set "decoded=%decoded:%%2A=*%" + set "decoded=%decoded:%%2B=+%" + set "decoded=%decoded:%%2C=,%" + set "decoded=%decoded:%%2D=-%" + set "decoded=%decoded:%%2E=.%" + set "decoded=%decoded:%%2F=/%" + :: ... Continue for other encodings ... + + :: Correct any double percentage signs + set "decoded=%decoded:%%%%=%" + +exit /b + + + +'@ +[io.file]::WriteAllText("$DIR\OpenWebSearch.cmd", $OpenWebSearch) + + +# Final Steps + +# Retrieve the Edge_Removal property from the specified registry paths +$userRegPaths = Get-ChildItem -Path 'Registry::HKEY_Users\S-1-5-21*\Volatile*' -ErrorAction SilentlyContinue +$edgeRemovalPath = $userRegPaths | Get-ItemProperty -Name 'Edge_Removal' -ErrorAction SilentlyContinue + +# If the Edge_Removal property exists, remove it +if ($edgeRemovalPath) { + Remove-ItemProperty -Path $edgeRemovalPath.PSPath -Name 'Edge_Removal' -Force -ErrorAction SilentlyContinue +} + +# Ensure the explorer process is running +if (-not (Get-Process -Name 'explorer' -ErrorAction SilentlyContinue)) { + Start-Process 'explorer' +} + + + diff --git a/functions/private/Get-WinUtilCheckBoxes.ps1 b/functions/private/Get-WinUtilCheckBoxes.ps1 index a572df04..fef27cc8 100644 --- a/functions/private/Get-WinUtilCheckBoxes.ps1 +++ b/functions/private/Get-WinUtilCheckBoxes.ps1 @@ -2,13 +2,19 @@ Function Get-WinUtilCheckBoxes { <# - .DESCRIPTION - Function is meant to find all checkboxes that are checked on the specific tab and input them into a script. + .SYNOPSIS + Finds all checkboxes that are checked on the specific tab and inputs them into a script. - Outputed data will be the names of the checkboxes that were checked + .PARAMETER Group + The group of checkboxes to check - .EXAMPLE + .PARAMETER unCheck + Whether to uncheck the checkboxes that are checked. Defaults to true + .OUTPUTS + A List containing the name of each checked checkbox + + .EXAMPLE Get-WinUtilCheckBoxes "WPFInstall" #> @@ -32,18 +38,18 @@ Function Get-WinUtilCheckBoxes { if ($uncheck -eq $true){ $CheckBox.value.ischecked = $false } - + } } } - + if($Group -eq "WPFTweaks"){ $filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPF*Tweaks*"} $CheckBoxes = $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} Foreach ($CheckBox in $CheckBoxes){ if($CheckBox.value.ischecked -eq $true){ $Output.Add($Checkbox.Name) - + if ($uncheck -eq $true){ $CheckBox.value.ischecked = $false } @@ -57,7 +63,7 @@ Function Get-WinUtilCheckBoxes { Foreach ($CheckBox in $CheckBoxes){ if($CheckBox.value.ischecked -eq $true){ $Output.Add($Checkbox.Name) - + if ($uncheck -eq $true){ $CheckBox.value.ischecked = $false } diff --git a/functions/private/Get-WinUtilInstallerProcess.ps1 b/functions/private/Get-WinUtilInstallerProcess.ps1 index a297b539..eae26476 100644 --- a/functions/private/Get-WinUtilInstallerProcess.ps1 +++ b/functions/private/Get-WinUtilInstallerProcess.ps1 @@ -1,9 +1,15 @@ function Get-WinUtilInstallerProcess { <# - - .DESCRIPTION - Meant to check for running processes and will return a boolean response - + + .SYNOPSIS + Checks if the given process is running + + .PARAMETER Process + The process to check + + .OUTPUTS + Boolean - True if the process is running + #> param($Process) diff --git a/functions/private/Get-WinUtilRegistry.ps1 b/functions/private/Get-WinUtilRegistry.ps1 index 33345a20..99b8e2f7 100644 --- a/functions/private/Get-WinUtilRegistry.ps1 +++ b/functions/private/Get-WinUtilRegistry.ps1 @@ -1,14 +1,13 @@ function Get-WinUtilRegistry { <# - - .DESCRIPTION - This function will make all modifications to the registry - .EXAMPLE + .SYNOPSIS + Gets the value of a registry key - Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" - - #> + .EXAMPLE + Get-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" + + #> param ( $Name, $Path, @@ -16,7 +15,7 @@ function Get-WinUtilRegistry { $Value ) - Try{ + Try{ $syscheckvalue = Get-ItemPropertyValue -Path $Path -Value $Value # Return Value } diff --git a/functions/private/Get-WinUtilToggleStatus.ps1 b/functions/private/Get-WinUtilToggleStatus.ps1 index a9742ff5..38d2d6e6 100644 --- a/functions/private/Get-WinUtilToggleStatus.ps1 +++ b/functions/private/Get-WinUtilToggleStatus.ps1 @@ -1,12 +1,15 @@ Function Get-WinUtilToggleStatus { <# - - .DESCRIPTION - Meant to pull the registry keys for a toggle switch and returns true or false - True should mean status is enabled - False should mean status is disabled - + .SYNOPSIS + Pulls the registry keys for the given toggle switch and checks whether the toggle should be checked or unchecked + + .PARAMETER ToggleSwitch + The name of the toggle to check + + .OUTPUTS + Boolean to set the toggle's status to + #> Param($ToggleSwitch) @@ -15,7 +18,7 @@ Function Get-WinUtilToggleStatus { $system = (Get-ItemProperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize').SystemUsesLightTheme if($app -eq 0 -and $system -eq 0){ return $true - } + } else{ return $false } @@ -24,7 +27,7 @@ Function Get-WinUtilToggleStatus { $bingsearch = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search').BingSearchEnabled if($bingsearch -eq 0){ return $false - } + } else{ return $true } diff --git a/functions/private/Get-WinUtilVariables.ps1 b/functions/private/Get-WinUtilVariables.ps1 index 32e536e4..cd0309cb 100644 --- a/functions/private/Get-WinUtilVariables.ps1 +++ b/functions/private/Get-WinUtilVariables.ps1 @@ -1,10 +1,13 @@ function Get-WinUtilVariables { <# - - .DESCRIPTION - placeholder - + + .SYNOPSIS + Gets every form object of the provided type + + .OUTPUTS + List containing every object that matches the provided type + #> param ( [Parameter()] @@ -12,7 +15,7 @@ function Get-WinUtilVariables { [string]$Type ) - $keys = $sync.keys | Where-Object {$psitem -like "WPF*"} + $keys = $sync.keys | Where-Object {$psitem -like "WPF*"} if($type){ $output = $keys | ForEach-Object { @@ -23,7 +26,7 @@ function Get-WinUtilVariables { } 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 9585858d..b96fc0e5 100644 --- a/functions/private/Install-WinUtilChoco.ps1 +++ b/functions/private/Install-WinUtilChoco.ps1 @@ -1,30 +1,29 @@ function Install-WinUtilChoco { <# - - .DESCRIPTION - Function is meant to ensure Choco is installed - + + .SYNOPSIS + Installs Chocolatey if it is not already installed + #> - 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?" - #Let user decide if he wants 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 - } + + 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 + } - Catch{ - throw [ChocoFailedInstall]::new('Failed to install') + Catch { + Write-Host "===========================================" + Write-Host "-- Chocolatey failed to install ---" + Write-Host "===========================================" } } diff --git a/functions/private/Install-WinUtilProgramWinget.ps1 b/functions/private/Install-WinUtilProgramWinget.ps1 index 13b2afde..dee2cb1f 100644 --- a/functions/private/Install-WinUtilProgramWinget.ps1 +++ b/functions/private/Install-WinUtilProgramWinget.ps1 @@ -1,12 +1,19 @@ Function Install-WinUtilProgramWinget { <# - - .DESCRIPTION - This will install programs via Winget using a new powershell.exe instance to prevent the GUI from locking up. - Note the triple quotes are required any time you need a " in a normal script block. - + .SYNOPSIS + Manages the provided programs using Winget + + .PARAMETER ProgramsToInstall + A list of programs to manage + + .PARAMETER manage + The action to perform on the programs, can be either 'Installing' or 'Uninstalling' + + .NOTES + The triple quotes are required any time you need a " in a normal script block. + #> param( @@ -20,7 +27,7 @@ Function Install-WinUtilProgramWinget { Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0 Foreach ($Program in $($ProgramsToInstall -split ",")){ - + Write-Progress -Activity "$manage Applications" -Status "$manage $Program $($x + 1) of $count" -PercentComplete $($x/$count*100) if($manage -eq "Installing"){ Start-Process -FilePath winget -ArgumentList "install -e --accept-source-agreements --accept-package-agreements --silent $Program" -NoNewWindow -Wait @@ -28,7 +35,7 @@ Function Install-WinUtilProgramWinget { if($manage -eq "Uninstalling"){ Start-Process -FilePath winget -ArgumentList "uninstall -e --purge --force --silent $Program" -NoNewWindow -Wait } - + $X++ } diff --git a/functions/private/Install-WinUtilWinget.ps1 b/functions/private/Install-WinUtilWinget.ps1 index 3681483c..0adfceb8 100644 --- a/functions/private/Install-WinUtilWinget.ps1 +++ b/functions/private/Install-WinUtilWinget.ps1 @@ -1,29 +1,29 @@ 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 - } +} function Install-WinUtilWinget { - + <# - - .DESCRIPTION - Function is meant to ensure winget is installed - + + .SYNOPSIS + Installs Winget if it is not already installed + #> Try{ Write-Host "Checking if Winget is Installed..." if (Test-WinUtilPackageManager -winget) { - #Checks if winget executable exists and if the Windows Version is 1809 or higher + # Checks if winget executable exists and if the Windows Version is 1809 or higher Write-Host "Winget Already Installed" return } - #Gets the computer's information + # Gets the computer's information if ($null -eq $sync.ComputerInfo){ $ComputerInfo = Get-ComputerInfo -ErrorAction Stop } @@ -32,14 +32,14 @@ function Install-WinUtilWinget { } if (($ComputerInfo.WindowsVersion) -lt "1809") { - #Checks if Windows Version is too old for winget + # Checks if Windows Version is too old for winget Write-Host "Winget is not supported on this version of Windows (Pre-1809)" return } Write-Host "Running Alternative Installer and Direct Installing" - Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "irm https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/winget.ps1 | iex" - + Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget" + Write-Host "Winget Installed" } Catch{ diff --git a/functions/private/Invoke-WinUtilBingSearch.ps1 b/functions/private/Invoke-WinUtilBingSearch.ps1 index 9d6fb56a..21574b68 100644 --- a/functions/private/Invoke-WinUtilBingSearch.ps1 +++ b/functions/private/Invoke-WinUtilBingSearch.ps1 @@ -1,9 +1,12 @@ function Invoke-WinUtilBingSearch { - <# - - .DESCRIPTION - Sets Bing Search on or off - + <# + + .SYNOPSIS + Disables/Enables Bing Search + + .PARAMETER Enabled + Indicates whether to enable or disable Bing Search + #> Param($Enabled) Try{ diff --git a/functions/private/Invoke-WinUtilCurrentSystem.ps1 b/functions/private/Invoke-WinUtilCurrentSystem.ps1 index ba8d3022..000dea4c 100644 --- a/functions/private/Invoke-WinUtilCurrentSystem.ps1 +++ b/functions/private/Invoke-WinUtilCurrentSystem.ps1 @@ -2,13 +2,10 @@ Function Invoke-WinUtilCurrentSystem { <# - .DESCRIPTION - Function is meant to read existing system registry and check according configuration. - - Example: Is telemetry enabled? check the box. - - .EXAMPLE + .SYNOPSIS + Checks to see what tweaks have already been applied and what programs are installed, and checks the according boxes + .EXAMPLE Get-WinUtilCheckBoxes "WPFInstall" #> @@ -46,19 +43,19 @@ Function Invoke-WinUtilCurrentSystem { $registryKeys = $sync.configs.tweaks.$Config.registry $scheduledtaskKeys = $sync.configs.tweaks.$Config.scheduledtask $serviceKeys = $sync.configs.tweaks.$Config.service - + if($registryKeys -or $scheduledtaskKeys -or $serviceKeys){ $Values = @() Foreach ($tweaks in $registryKeys){ Foreach($tweak in $tweaks){ - + if(test-path $tweak.Path){ $actualValue = Get-ItemProperty -Name $tweak.Name -Path $tweak.Path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $($tweak.Name) $expectedValue = $tweak.Value if ($expectedValue -notlike $actualValue){ - $values += $False + $values += $False } } } @@ -67,7 +64,7 @@ Function Invoke-WinUtilCurrentSystem { Foreach ($tweaks in $scheduledtaskKeys){ Foreach($tweak in $tweaks){ $task = $ScheduledTasks | Where-Object {$($psitem.TaskPath + $psitem.TaskName) -like "\$($tweak.name)"} - + if($task){ $actualValue = $task.State $expectedValue = $tweak.State @@ -81,7 +78,7 @@ Function Invoke-WinUtilCurrentSystem { Foreach ($tweaks in $serviceKeys){ Foreach($tweak in $tweaks){ $Service = Get-Service -Name $tweak.Name - + if($Service){ $actualValue = $Service.StartType $expectedValue = $tweak.StartupType diff --git a/functions/private/Invoke-WinUtilDarkMode.ps1 b/functions/private/Invoke-WinUtilDarkMode.ps1 index c8002477..52a917de 100644 --- a/functions/private/Invoke-WinUtilDarkMode.ps1 +++ b/functions/private/Invoke-WinUtilDarkMode.ps1 @@ -1,9 +1,12 @@ Function Invoke-WinUtilDarkMode { - <# - - .DESCRIPTION - Sets Dark Mode on or off - + <# + + .SYNOPSIS + Enables/Disables Dark Mode + + .PARAMETER DarkMoveEnabled + Indicates the current dark mode state + #> Param($DarkMoveEnabled) Try{ @@ -15,7 +18,7 @@ Function Invoke-WinUtilDarkMode { Write-Host "Disabling Dark Mode" $DarkMoveValue = 1 } - + $Theme = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" Set-ItemProperty -Path $Theme -Name AppsUseLightTheme -Value $DarkMoveValue Set-ItemProperty -Path $Theme -Name SystemUsesLightTheme -Value $DarkMoveValue diff --git a/functions/private/Invoke-WinUtilFeatureInstall.ps1 b/functions/private/Invoke-WinUtilFeatureInstall.ps1 index e5968ee5..8fc6ee2c 100644 --- a/functions/private/Invoke-WinUtilFeatureInstall.ps1 +++ b/functions/private/Invoke-WinUtilFeatureInstall.ps1 @@ -1,9 +1,9 @@ function Invoke-WinUtilFeatureInstall { <# - - .DESCRIPTION - This function converts all the values from the tweaks.json and routes them to the appropriate function - + + .SYNOPSIS + Converts all the values from the tweaks.json and routes them to the appropriate function + #> param( @@ -13,7 +13,7 @@ function Invoke-WinUtilFeatureInstall { $CheckBox | ForEach-Object { if($sync.configs.feature.$psitem.feature){ Foreach( $feature in $sync.configs.feature.$psitem.feature ){ - Try{ + Try{ Write-Host "Installing $feature" Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart } @@ -24,10 +24,10 @@ function Invoke-WinUtilFeatureInstall { else{ Write-Warning "Unable to Install $feature due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } - } + } } if($sync.configs.feature.$psitem.InvokeScript){ Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ){ @@ -44,10 +44,10 @@ function Invoke-WinUtilFeatureInstall { else{ Write-Warning "Unable to Install $feature due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } - } + } } } } diff --git a/functions/private/Invoke-WinUtilScript.ps1 b/functions/private/Invoke-WinUtilScript.ps1 index 329f76f9..4059f917 100644 --- a/functions/private/Invoke-WinUtilScript.ps1 +++ b/functions/private/Invoke-WinUtilScript.ps1 @@ -1,14 +1,19 @@ function Invoke-WinUtilScript { <# - - .DESCRIPTION - This function will run a separate powershell script. Meant for things that can't be handled with the other functions - .EXAMPLE + .SYNOPSIS + Invokes the provided scriptblock. Intended for things that can't be handled with the other functions. + .PARAMETER Name + The name of the scriptblock being invoked + + .PARAMETER scriptblock + The scriptblock to be invoked + + .EXAMPLE $Scriptblock = [scriptblock]::Create({"Write-output 'Hello World'"}) Invoke-WinUtilScript -ScriptBlock $scriptblock -Name "Hello World" - + #> param ( $Name, @@ -38,7 +43,7 @@ function Invoke-WinUtilScript { Catch { # Generic catch block to handle any other type of exception Write-Warning "Unable to run script for $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } - + } \ No newline at end of file diff --git a/functions/private/Invoke-WinUtilTweaks.ps1 b/functions/private/Invoke-WinUtilTweaks.ps1 index a345b0a1..e57a6e73 100644 --- a/functions/private/Invoke-WinUtilTweaks.ps1 +++ b/functions/private/Invoke-WinUtilTweaks.ps1 @@ -1,9 +1,15 @@ function Invoke-WinUtilTweaks { <# - - .DESCRIPTION - This function converts all the values from the tweaks.json and routes them to the appropriate function - + + .SYNOPSIS + Invokes the function associated with each provided checkbox + + .PARAMETER CheckBox + The checkbox to invoke + + .PARAMETER undo + Indicates whether to undo the operation contained in the checkbox + #> param( @@ -18,7 +24,7 @@ function Invoke-WinUtilTweaks { ScriptType = "UndoScript" } - } + } Else{ $Values = @{ Registry = "Value" diff --git a/functions/private/Remove-WinUtilAPPX.ps1 b/functions/private/Remove-WinUtilAPPX.ps1 index dd6c25bd..db6471a5 100644 --- a/functions/private/Remove-WinUtilAPPX.ps1 +++ b/functions/private/Remove-WinUtilAPPX.ps1 @@ -1,13 +1,15 @@ function Remove-WinUtilAPPX { <# - - .DESCRIPTION - This function will remove any of the provided APPX names - .EXAMPLE + .SYNOPSIS + Removes all APPX packages that match the given name + .PARAMETER Name + The name of the APPX package to remove + + .EXAMPLE Remove-WinUtilAPPX -Name "Microsoft.Microsoft3DViewer" - + #> param ( $Name @@ -24,11 +26,11 @@ function Remove-WinUtilAPPX { } Else{ Write-Warning "Unable to uninstall $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } Catch{ Write-Warning "Unable to uninstall $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } \ No newline at end of file diff --git a/functions/private/Set-WinUtilDNS.ps1 b/functions/private/Set-WinUtilDNS.ps1 index daf7e752..314a5ac8 100644 --- a/functions/private/Set-WinUtilDNS.ps1 +++ b/functions/private/Set-WinUtilDNS.ps1 @@ -1,13 +1,15 @@ function Set-WinUtilDNS { <# - - .DESCRIPTION - This function will set the DNS of all interfaces that are in the "Up" state. It will lookup the values from the DNS.Json file - .EXAMPLE + .SYNOPSIS + Sets the DNS of all interfaces that are in the "Up" state. It will lookup the values from the DNS.Json file + .PARAMETER DNSProvider + The DNS provider to set the DNS server to + + .EXAMPLE Set-WinUtilDNS -DNSProvider "google" - + #> param($DNSProvider) if($DNSProvider -eq "Default"){return} @@ -27,6 +29,6 @@ function Set-WinUtilDNS { } Catch{ Write-Warning "Unable to set DNS Provider due to an unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } diff --git a/functions/private/Set-WinUtilRegistry.ps1 b/functions/private/Set-WinUtilRegistry.ps1 index 58be4345..a5c67fbc 100644 --- a/functions/private/Set-WinUtilRegistry.ps1 +++ b/functions/private/Set-WinUtilRegistry.ps1 @@ -1,14 +1,25 @@ function Set-WinUtilRegistry { <# - - .DESCRIPTION - This function will make all modifications to the registry - .EXAMPLE + .SYNOPSIS + Modifies the registry based on the given inputs + .PARAMETER Name + The name of the key to modify + + .PARAMETER Path + The path to the key + + .PARAMETER Type + The type of value to set the key to + + .PARAMETER Value + The value to set the key to + + .EXAMPLE Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" - - #> + + #> param ( $Name, $Path, @@ -16,7 +27,7 @@ function Set-WinUtilRegistry { $Value ) - Try{ + Try{ if(!(Test-Path 'HKU:\')){New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS} If (!(Test-Path $Path)) { diff --git a/functions/private/Set-WinUtilRestorePoint.ps1 b/functions/private/Set-WinUtilRestorePoint.ps1 index 3fd73403..79618a12 100644 --- a/functions/private/Set-WinUtilRestorePoint.ps1 +++ b/functions/private/Set-WinUtilRestorePoint.ps1 @@ -1,10 +1,10 @@ function Set-WinUtilRestorePoint { <# - - .DESCRIPTION - This function will make a Restore Point - #> + .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)) { @@ -24,7 +24,7 @@ function Set-WinUtilRestorePoint { $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 + 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 @@ -33,7 +33,7 @@ function Set-WinUtilRestorePoint { # 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/private/Set-WinUtilScheduledTask.ps1 b/functions/private/Set-WinUtilScheduledTask.ps1 index fc1c07e3..453f7793 100644 --- a/functions/private/Set-WinUtilScheduledTask.ps1 +++ b/functions/private/Set-WinUtilScheduledTask.ps1 @@ -1,13 +1,18 @@ function Set-WinUtilScheduledTask { <# - - .DESCRIPTION - This function will enable/disable the provided Scheduled Task - .EXAMPLE + .SYNOPSIS + Enables/Disables the provided Scheduled Task + .PARAMETER Name + The path to the Scheduled Task + + .PARAMETER State + The State to set the Task to + + .EXAMPLE Set-WinUtilScheduledTask -Name "Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -State "Disabled" - + #> param ( $Name, @@ -35,6 +40,6 @@ function Set-WinUtilScheduledTask { } Catch{ Write-Warning "Unable to run script for $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } \ No newline at end of file diff --git a/functions/private/Set-WinUtilService.ps1 b/functions/private/Set-WinUtilService.ps1 index ee03944b..e16b2597 100644 --- a/functions/private/Set-WinUtilService.ps1 +++ b/functions/private/Set-WinUtilService.ps1 @@ -1,24 +1,29 @@ Function Set-WinUtilService { <# - - .DESCRIPTION - This function will change the startup type of services and start/stop them as needed - .EXAMPLE + .SYNOPSIS + Changes the startup type of the given service + .PARAMETER Name + The name of the service to modify + + .PARAMETER StartupType + The startup type to set the service to + + .EXAMPLE Set-WinUtilService -Name "HomeGroupListener" -StartupType "Manual" - - #> + + #> param ( $Name, $StartupType ) try { Write-Host "Setting Service $Name to $StartupType" - + # Check if the service exists $service = Get-Service -Name $Name -ErrorAction Stop - + # Service exists, proceed with changing properties $service | Set-Service -StartupType $StartupType -ErrorAction Stop } @@ -29,5 +34,5 @@ Function Set-WinUtilService { Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $_.Exception.Message } - + } diff --git a/functions/private/Set-WinUtilUiTheme.ps1 b/functions/private/Set-WinUtilUiTheme.ps1 index 5cd3eeb7..46d55afa 100644 --- a/functions/private/Set-WinUtilUiTheme.ps1 +++ b/functions/private/Set-WinUtilUiTheme.ps1 @@ -1,13 +1,18 @@ function Set-WinUtilUITheme { <# - - .DESCRIPTION - This function will set theme to the XAML file - .EXAMPLE + .SYNOPSIS + Sets the theme of the XAML file + .PARAMETER inputXML + A string representing the XAML object to modify + + .PARAMETER themeName + The name of the theme to set the XAML to. Defaults to 'matrix' + + .EXAMPLE Set-WinUtilUITheme -inputXAML $inputXAML - + #> param ( @@ -41,7 +46,7 @@ function Set-WinUtilUITheme { } catch { Write-Warning "Unable to apply theme" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } return $inputXML; diff --git a/functions/private/Test-WinUtilPackageManager.ps1 b/functions/private/Test-WinUtilPackageManager.ps1 index a4624c53..b548265a 100644 --- a/functions/private/Test-WinUtilPackageManager.ps1 +++ b/functions/private/Test-WinUtilPackageManager.ps1 @@ -1,9 +1,15 @@ function Test-WinUtilPackageManager { <# - - .DESCRIPTION - Checks for Winget or Choco depending on the parameter - + + .SYNOPSIS + Checks if Winget and/or Choco are installed + + .PARAMETER winget + Check if Winget is installed + + .PARAMETER choco + Check if Chocolatey is installed + #> Param( diff --git a/functions/private/Update-WinUtilProgramWinget.ps1 b/functions/private/Update-WinUtilProgramWinget.ps1 index 6835972f..5deac59c 100644 --- a/functions/private/Update-WinUtilProgramWinget.ps1 +++ b/functions/private/Update-WinUtilProgramWinget.ps1 @@ -1,10 +1,10 @@ Function Update-WinUtilProgramWinget { <# - - .DESCRIPTION - This will update programs via Winget using a new powershell.exe instance to prevent the GUI from locking up. - + + .SYNOPSIS + This will update all programs using Winget + #> [ScriptBlock]$wingetinstall = { diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index cdb1da5e..01bb9fcd 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -1,17 +1,18 @@ function Invoke-WPFButton { <# - - .DESCRIPTION - Meant to make creating buttons easier. There is a section below in the gui that will assign this function to every button. - This way you can dictate what each button does from this function. - - Input will be the name of the button that is clicked. - #> - - Param ([string]$Button) - #Use this to get the name of the button + .SYNOPSIS + Invokes the function associated with the clicked button + + .PARAMETER Button + The name of the button that was clicked + + #> + + 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") Switch -Wildcard ($Button){ diff --git a/functions/public/Invoke-WPFControlPanel.ps1 b/functions/public/Invoke-WPFControlPanel.ps1 index 713ec3cd..f5574a11 100644 --- a/functions/public/Invoke-WPFControlPanel.ps1 +++ b/functions/public/Invoke-WPFControlPanel.ps1 @@ -1,9 +1,12 @@ function Invoke-WPFControlPanel { - <# - - .DESCRIPTION - Simple Switch for legacy windows - + <# + + .SYNOPSIS + Opens the requested legacy panel + + .PARAMETER Panel + The panel to open + #> param($Panel) diff --git a/functions/public/Invoke-WPFFeatureInstall.ps1 b/functions/public/Invoke-WPFFeatureInstall.ps1 index 70411ce0..2277b753 100644 --- a/functions/public/Invoke-WPFFeatureInstall.ps1 +++ b/functions/public/Invoke-WPFFeatureInstall.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFFeatureInstall { - <# - - .DESCRIPTION - GUI Function to install Windows Features - + <# + + .SYNOPSIS + Installs selected Windows Features + #> if($sync.ProcessRunning){ @@ -26,12 +26,12 @@ function Invoke-WPFFeatureInstall { Write-Host "--- Features are Installed ---" Write-Host "--- A Reboot may be required ---" Write-Host "===================================" - + $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "All features are now installed " $Messageboxbody = ("Done") $MessageIcon = [System.Windows.MessageBoxImage]::Information - + [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) } } \ No newline at end of file diff --git a/functions/public/Invoke-WPFFixesNetwork.ps1 b/functions/public/Invoke-WPFFixesNetwork.ps1 index 614c0567..94ba11bd 100644 --- a/functions/public/Invoke-WPFFixesNetwork.ps1 +++ b/functions/public/Invoke-WPFFixesNetwork.ps1 @@ -1,14 +1,18 @@ function Invoke-WPFFixesNetwork { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Resets various network configurations + #> Write-Host "Resetting Network with netsh" + + # Reset WinSock catalog to a clean state Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winsock", "reset" + # Resets WinHTTP proxy setting to DIRECT Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winhttp", "reset", "proxy" + # Removes all user configured IP settings Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "int", "ip", "reset" Write-Host "Process complete. Please reboot your computer." @@ -19,7 +23,7 @@ function Invoke-WPFFixesNetwork { $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) - Write-Host "=================================" - Write-Host "-- Reset Network Configuration --" - Write-Host "=================================" + Write-Host "==========================================" + Write-Host "-- Network Configuration has been Reset --" + Write-Host "==========================================" } \ No newline at end of file diff --git a/functions/public/Invoke-WPFFixesUpdate.ps1 b/functions/public/Invoke-WPFFixesUpdate.ps1 index c23449ac..7e170b53 100644 --- a/functions/public/Invoke-WPFFixesUpdate.ps1 +++ b/functions/public/Invoke-WPFFixesUpdate.ps1 @@ -1,13 +1,13 @@ function Invoke-WPFFixesUpdate { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Performs various tasks in an attempt to repair Windows Update + #> - ### Reset Windows Update Script - reregister dlls, services, and remove registry entries. + # Reset Windows Update Script - reregister dlls, services, and remove registry entries Write-Host "1. Stopping Windows Update Services..." Stop-Service -Name BITS Stop-Service -Name wuauserv @@ -83,7 +83,7 @@ Write-Host "12) Forcing discovery..." $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) - Write-Host "=================================" - Write-Host "-- Reset ALL Updates to Factory -" - Write-Host "=================================" + Write-Host "===============================================" + Write-Host "-- Reset All Windows Update Settings to Stock -" + Write-Host "===============================================" } \ No newline at end of file diff --git a/functions/public/Invoke-WPFFormVariables.ps1 b/functions/public/Invoke-WPFFormVariables.ps1 index f2e4a3d2..5905e0f8 100644 --- a/functions/public/Invoke-WPFFormVariables.ps1 +++ b/functions/public/Invoke-WPFFormVariables.ps1 @@ -1,9 +1,9 @@ Function Invoke-WPFFormVariables { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Prints the logo + #> #If ($global:ReadmeDisplay -ne $true) { Write-Host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow; $global:ReadmeDisplay = $true } diff --git a/functions/public/Invoke-WPFGetInstalled.ps1 b/functions/public/Invoke-WPFGetInstalled.ps1 index 09a296fb..001cce2b 100644 --- a/functions/public/Invoke-WPFGetInstalled.ps1 +++ b/functions/public/Invoke-WPFGetInstalled.ps1 @@ -1,8 +1,11 @@ function Invoke-WPFGetInstalled { <# - .DESCRIPTION - placeholder + .SYNOPSIS + Invokes the function that gets the checkboxes to check in a new runspace + + .PARAMETER checkbox + Indicates whether to check for installed 'winget' programs or applied 'tweaks' #> param($checkbox) @@ -31,9 +34,9 @@ function Invoke-WPFGetInstalled { if($checkbox -eq "tweaks"){ Write-Host "Getting Installed Tweaks..." } - + $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox - + $sync.form.Dispatcher.invoke({ foreach($checkbox in $Checkboxes){ $sync.$checkbox.ischecked = $True diff --git a/functions/public/Invoke-WPFImpex.ps1 b/functions/public/Invoke-WPFImpex.ps1 index a6a14b23..f02de2ed 100644 --- a/functions/public/Invoke-WPFImpex.ps1 +++ b/functions/public/Invoke-WPFImpex.ps1 @@ -1,13 +1,18 @@ function Invoke-WPFImpex { <# - - .DESCRIPTION - This function handles importing and exporting of the checkboxes checked for the tweaks section - .EXAMPLE + .SYNOPSIS + Handles importing and exporting of the checkboxes checked for the tweaks section + .PARAMETER type + Indicates whether to 'import' or 'export' + + .PARAMETER checkbox + The checkbox to export to a file or apply the imported file to + + .EXAMPLE Invoke-WPFImpex -type "export" - + #> param( $type, @@ -18,7 +23,7 @@ function Invoke-WPFImpex { $FileBrowser = New-Object System.Windows.Forms.SaveFileDialog } if ($type -eq "import"){ - $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog + $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog } $FileBrowser.InitialDirectory = [Environment]::GetFolderPath('Desktop') @@ -28,7 +33,7 @@ function Invoke-WPFImpex { if($FileBrowser.FileName -eq ""){ return } - + if ($type -eq "export"){ $jsonFile = Get-WinUtilCheckBoxes $checkbox -unCheck $false $jsonFile | ConvertTo-Json | Out-File $FileBrowser.FileName -Force diff --git a/functions/public/Invoke-WPFInstall.ps1 b/functions/public/Invoke-WPFInstall.ps1 index 484f4b27..89dd0b49 100644 --- a/functions/public/Invoke-WPFInstall.ps1 +++ b/functions/public/Invoke-WPFInstall.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFInstall { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Installs the selected programs using winget + #> if($sync.ProcessRunning){ @@ -28,14 +28,14 @@ function Invoke-WPFInstall { # Ensure winget is installed Install-WinUtilWinget - # Install all winget programs in new window + # 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 "===========================================" diff --git a/functions/public/Invoke-WPFInstallUpgrade.ps1 b/functions/public/Invoke-WPFInstallUpgrade.ps1 index 8e5e31f1..c2fb9df1 100644 --- a/functions/public/Invoke-WPFInstallUpgrade.ps1 +++ b/functions/public/Invoke-WPFInstallUpgrade.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFInstallUpgrade { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Invokes the function that upgrades all installed programs using winget + #> if(!(Test-WinUtilPackageManager -winget)){ Write-Host "===========================================" diff --git a/functions/public/Invoke-WPFPanelAutologin.ps1 b/functions/public/Invoke-WPFPanelAutologin.ps1 index 1cd14ef9..5291869a 100644 --- a/functions/public/Invoke-WPFPanelAutologin.ps1 +++ b/functions/public/Invoke-WPFPanelAutologin.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFPanelAutologin { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Enables autologin using Sysinternals Autologon.exe + #> curl.exe -ss "https://live.sysinternals.com/Autologon.exe" -o $env:temp\autologin.exe # Official Microsoft recommendation https://learn.microsoft.com/en-us/sysinternals/downloads/autologon cmd /c $env:temp\autologin.exe /accepteula diff --git a/functions/public/Invoke-WPFPanelDISM.ps1 b/functions/public/Invoke-WPFPanelDISM.ps1 index 9212682c..a1d266cf 100644 --- a/functions/public/Invoke-WPFPanelDISM.ps1 +++ b/functions/public/Invoke-WPFPanelDISM.ps1 @@ -1,9 +1,26 @@ function Invoke-WPFPanelDISM { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Checks for system corruption using Chkdsk, SFC, and DISM + + .DESCRIPTION + 1. Chkdsk - Fixes disk and filesystem corruption + 2. SFC Run 1 - Fixes system file corruption, and fixes DISM if it was corrupted + 3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted + 4. SFC Run 2 - Fixes system file corruption, this time with an almost guaranteed uncorrupted system image + + .NOTES + Command Arguments: + 1. Chkdsk + /Scan - Runs an online scan on the system drive, attempts to fix any corruption, and queues other corruption for fixing on reboot + 2. SFC + /ScanNow - Performs a scan of the system files and fixes any corruption + 3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted + /Online - Fixes the currently running system image + /Cleanup-Image - Performs cleanup operations on the image, could remove some unneeded temporary files + /Restorehealth - Performs a scan of the image and fixes any corruption + #> Start-Process PowerShell -ArgumentList "Write-Host '(1/4) Chkdsk' -ForegroundColor Green; Chkdsk /scan; Write-Host '`n(2/4) SFC - 1st scan' -ForegroundColor Green; sfc /scannow; diff --git a/functions/public/Invoke-WPFPresets.ps1 b/functions/public/Invoke-WPFPresets.ps1 index 6e535714..4b61e40b 100644 --- a/functions/public/Invoke-WPFPresets.ps1 +++ b/functions/public/Invoke-WPFPresets.ps1 @@ -1,8 +1,17 @@ function Invoke-WPFPresets { <# - .DESCRIPTION - Meant to make settings presets easier in the tweaks tab. Will pull the data from config/preset.json + .SYNOPSIS + Sets the options in the tweaks panel to the given preset + + .PARAMETER preset + The preset to set the options to + + .PARAMETER imported + If the preset is imported from a file, defaults to false + + .PARAMETER checkbox + The checkbox to set the options to, defaults to 'WPFTweaks' #> diff --git a/functions/public/Invoke-WPFRunspace.ps1 b/functions/public/Invoke-WPFRunspace.ps1 index e00b42bf..975f44a7 100644 --- a/functions/public/Invoke-WPFRunspace.ps1 +++ b/functions/public/Invoke-WPFRunspace.ps1 @@ -1,40 +1,41 @@ function Invoke-WPFRunspace { <# - - .DESCRIPTION - Simple function to make it easier to invoke a runspace from inside the script. - .EXAMPLE + .SYNOPSIS + Creates and invokes a runspace using the given scriptblock and argumentlist - $params = @{ - ScriptBlock = $sync.ScriptsInstallPrograms - ArgumentList = "Installadvancedip,Installbitwarden" - Verbose = $true - } + .PARAMETER ScriptBlock + The scriptblock to invoke in the runspace + + .PARAMETER ArgumentList + A list of arguments to pass to the runspace + + .EXAMPLE + Invoke-WPFRunspace ` + -ScriptBlock $sync.ScriptsInstallPrograms ` + -ArgumentList "Installadvancedip,Installbitwarden" ` - Invoke-WPFRunspace @params - #> [CmdletBinding()] Param ( $ScriptBlock, $ArgumentList - ) + ) - #Crate a PowerShell instance. + # Create a PowerShell instance $script:powershell = [powershell]::Create() - #Add Scriptblock and Arguments to runspace + # Add Scriptblock and Arguments to runspace $script:powershell.AddScript($ScriptBlock) $script:powershell.AddArgument($ArgumentList) $script:powershell.RunspacePool = $sync.runspace - - #Run our RunspacePool. + + # Execute the RunspacePool $script:handle = $script:powershell.BeginInvoke() - #Cleanup our RunspacePool threads when they are complete ie. GC. + # Clean up the RunspacePool threads when they are complete, and invoke the garbage collector to clean up the memory if ($script:handle.IsCompleted) { $script:powershell.EndInvoke($script:handle) diff --git a/functions/public/Invoke-WPFShortcut.ps1 b/functions/public/Invoke-WPFShortcut.ps1 index 1b0377f8..75c3155a 100644 --- a/functions/public/Invoke-WPFShortcut.ps1 +++ b/functions/public/Invoke-WPFShortcut.ps1 @@ -1,15 +1,18 @@ function Invoke-WPFShortcut { <# - .DESCRIPTION - Creates a shortcut + .SYNOPSIS + Creates a shortcut and prompts for a save location + + .PARAMETER ShortcutToAdd + The name of the shortcut to add #> param($ShortcutToAdd) Switch ($ShortcutToAdd) { "WinUtil" { - $SourceExe = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" + $SourceExe = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" $IRM = 'irm https://christitus.com/win | iex' $Powershell = '-ExecutionPolicy Bypass -Command "Start-Process powershell.exe -verb runas -ArgumentList' $ArgumentsToSourceExe = "$powershell '$IRM'" @@ -28,6 +31,6 @@ function Invoke-WPFShortcut { $Shortcut.TargetPath = $SourceExe $Shortcut.Arguments = $ArgumentsToSourceExe $Shortcut.Save() - + Write-Host "Shortcut for $ShortcutToAdd has been saved to $($FileBrowser.FileName)" } \ No newline at end of file diff --git a/functions/public/Invoke-WPFTab.ps1 b/functions/public/Invoke-WPFTab.ps1 index 21976956..14d26c5e 100644 --- a/functions/public/Invoke-WPFTab.ps1 +++ b/functions/public/Invoke-WPFTab.ps1 @@ -1,10 +1,13 @@ function Invoke-WPFTab { <# - - .DESCRIPTION - Sole purpose of this function is to reduce duplicated code for switching between tabs. - + + .SYNOPSIS + Sets the selected tab to the tab that was clicked + + .PARAMETER ClickedTab + The name of the tab that was clicked + #> Param ($ClickedTab) @@ -13,7 +16,7 @@ function Invoke-WPFTab { $x = [int]($ClickedTab -replace "WPFTab","" -replace "BT","") - 1 0..($Tabs.Count -1 ) | ForEach-Object { - + if ($x -eq $psitem){ $sync.$TabNav.Items[$psitem].IsSelected = $true } diff --git a/functions/public/Invoke-WPFToggle.ps1 b/functions/public/Invoke-WPFToggle.ps1 index 451c950d..1ab6de6b 100644 --- a/functions/public/Invoke-WPFToggle.ps1 +++ b/functions/public/Invoke-WPFToggle.ps1 @@ -1,17 +1,18 @@ function Invoke-WPFToggle { <# - - .DESCRIPTION - Meant to make creating toggle switches easier. There is a section below in the gui that will assign this function to every switch. - This way you can dictate what each button does from this function. - - Input will be the name of the toggle that is checked. - #> - - Param ([string]$Button) - #Use this to get the name of the button + .SYNOPSIS + Invokes the scriptblock for the given toggle + + .PARAMETER Button + The name of the toggle to invoke + + #> + + 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") Switch -Wildcard ($Button){ diff --git a/functions/public/Invoke-WPFUltimatePerformance.ps1 b/functions/public/Invoke-WPFUltimatePerformance.ps1 index 014bcc2d..28d4c241 100644 --- a/functions/public/Invoke-WPFUltimatePerformance.ps1 +++ b/functions/public/Invoke-WPFUltimatePerformance.ps1 @@ -1,46 +1,51 @@ Function Invoke-WPFUltimatePerformance { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Creates or removes the Ultimate Performance power scheme + + .PARAMETER State + Indicates whether to enable or disable the Ultimate Performance power scheme + #> param($State) Try{ if($state -eq "Enabled"){ - # Define the name and GUID of the power scheme you want to add + # Define the name and GUID of the power scheme $powerSchemeName = "Ultimate Performance" $powerSchemeGuid = "e9a42b02-d5df-448d-aa00-03f14749eb61" # Get all power schemes $schemes = powercfg /list | Out-String -Stream - # Find the scheme you want to add + # Check if the power scheme already exists $ultimateScheme = $schemes | Where-Object { $_ -match $powerSchemeName } - # If the scheme does not exist, add it if ($null -eq $ultimateScheme) { Write-Host "Power scheme '$powerSchemeName' not found. Adding..." # Add the power scheme powercfg /duplicatescheme $powerSchemeGuid powercfg -attributes SUB_SLEEP 7bc4a2f9-d8fc-4469-b07b-33eb785aaca0 -ATTRIB_HIDE + powercfg -setactive $powerSchemeGuid + powercfg -change -monitor-timeout-ac 0 + Write-Host "Power scheme added successfully." } else { Write-Host "Power scheme '$powerSchemeName' already exists." - } + } } elseif($state -eq "Disabled"){ - # Define the name of the power scheme you want to remove + # Define the name of the power scheme $powerSchemeName = "Ultimate Performance" # Get all power schemes $schemes = powercfg /list | Out-String -Stream - # Find the scheme you want to remove + # Find the scheme to be removed $ultimateScheme = $schemes | Where-Object { $_ -match $powerSchemeName } # If the scheme exists, remove it @@ -50,10 +55,10 @@ Function Invoke-WPFUltimatePerformance { if($null -ne $guid){ Write-Host "Found power scheme '$powerSchemeName' with GUID $guid. Removing..." - + # Remove the power scheme powercfg /delete $guid - + Write-Host "Power scheme removed successfully." } else { @@ -65,7 +70,7 @@ Function Invoke-WPFUltimatePerformance { } } - + } Catch{ Write-Warning $psitem.Exception.Message diff --git a/functions/public/Invoke-WPFUnInstall.ps1 b/functions/public/Invoke-WPFUnInstall.ps1 index 2205db15..81cfc57c 100644 --- a/functions/public/Invoke-WPFUnInstall.ps1 +++ b/functions/public/Invoke-WPFUnInstall.ps1 @@ -1,13 +1,13 @@ function Invoke-WPFUnInstall { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Uninstalls the selected programs + #> if($sync.ProcessRunning){ - $msg = "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 } @@ -22,7 +22,7 @@ function Invoke-WPFUnInstall { $ButtonType = [System.Windows.MessageBoxButton]::YesNo $MessageboxTitle = "Are you sure?" - $Messageboxbody = ("This will uninstall the following applications `n $WingetInstall") + $Messageboxbody = ("This will uninstall the following applications: `n $WingetInstall") $MessageIcon = [System.Windows.MessageBoxImage]::Information $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) @@ -34,23 +34,23 @@ function Invoke-WPFUnInstall { try{ $sync.ProcessRunning = $true - # Install all winget programs in new window + # Install all selected programs in new window Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall -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) Write-Host "===========================================" - Write-Host "-- Uninstalls have finished ---" + Write-Host "-- Uninstalls have finished ---" Write-Host "===========================================" } Catch { Write-Host "===========================================" - Write-Host "-- Winget failed to install ---" + Write-Host "-- Winget failed to install ---" Write-Host "===========================================" } $sync.ProcessRunning = $False diff --git a/functions/public/Invoke-WPFUpdatesdefault.ps1 b/functions/public/Invoke-WPFUpdatesdefault.ps1 index fb6caff7..3e1cebdd 100644 --- a/functions/public/Invoke-WPFUpdatesdefault.ps1 +++ b/functions/public/Invoke-WPFUpdatesdefault.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFUpdatesdefault { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Resets Windows Update settings to default + #> If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null @@ -39,7 +39,7 @@ function Invoke-WPFUpdatesdefault { Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "BranchReadinessLevel" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferFeatureUpdatesPeriodInDays" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferQualityUpdatesPeriodInDays" -ErrorAction SilentlyContinue - Write-Host "=================================" - Write-Host "--- Updates Set to Default ---" - Write-Host "=================================" + Write-Host "===================================================" + Write-Host "--- Windows Update Settings Reset to Default ---" + Write-Host "===================================================" } \ No newline at end of file diff --git a/functions/public/Invoke-WPFUpdatesdisable.ps1 b/functions/public/Invoke-WPFUpdatesdisable.ps1 index 4cff5f5d..3167039f 100644 --- a/functions/public/Invoke-WPFUpdatesdisable.ps1 +++ b/functions/public/Invoke-WPFUpdatesdisable.ps1 @@ -1,9 +1,12 @@ function Invoke-WPFUpdatesdisable { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Disables Windows Update + + .NOTES + Disabling Windows Update is not recommended. This is only for advanced users who know what they are doing. + #> If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null @@ -27,6 +30,6 @@ function Invoke-WPFUpdatesdisable { Get-Service -Name $service -ErrorAction SilentlyContinue | Set-Service -StartupType Disabled } Write-Host "=================================" - Write-Host "--- Updates ARE DISABLED ---" + Write-Host "--- Updates ARE DISABLED ---" Write-Host "=================================" } \ No newline at end of file diff --git a/functions/public/Invoke-WPFUpdatessecurity.ps1 b/functions/public/Invoke-WPFUpdatessecurity.ps1 index a40cf677..e310d6a4 100644 --- a/functions/public/Invoke-WPFUpdatessecurity.ps1 +++ b/functions/public/Invoke-WPFUpdatessecurity.ps1 @@ -1,9 +1,16 @@ function Invoke-WPFUpdatessecurity { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Sets Windows Update to recommended settings + + .DESCRIPTION + 1. Disables driver offering through Windows Update + 2. Disables Windows Update automatic restart + 3. Sets Windows Update to Semi-Annual Channel (Targeted) + 4. Defers feature updates for 365 days + 5. Defers quality updates for 4 days + #> Write-Host "Disabling driver offering through Windows Update..." If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata")) { diff --git a/functions/public/Invoke-WPFtweaksbutton.ps1 b/functions/public/Invoke-WPFtweaksbutton.ps1 index 07a0a89c..a037653e 100644 --- a/functions/public/Invoke-WPFtweaksbutton.ps1 +++ b/functions/public/Invoke-WPFtweaksbutton.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFtweaksbutton { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Invokes the functions associated with each group of checkboxes + #> if($sync.ProcessRunning){ @@ -22,13 +22,13 @@ function Invoke-WPFtweaksbutton { return } - Set-WinUtilRestorePoint - Invoke-WPFRunspace -ArgumentList $Tweaks -ScriptBlock { param($Tweaks) $sync.ProcessRunning = $true + Set-WinUtilRestorePoint + Foreach ($tweak in $tweaks){ Invoke-WinUtilTweaks $tweak } diff --git a/functions/public/Invoke-WPFundoall.ps1 b/functions/public/Invoke-WPFundoall.ps1 index 272636d3..76eff6cc 100644 --- a/functions/public/Invoke-WPFundoall.ps1 +++ b/functions/public/Invoke-WPFundoall.ps1 @@ -1,9 +1,9 @@ function Invoke-WPFundoall { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Undoes every selected tweak + #> if($sync.ProcessRunning){ @@ -18,8 +18,8 @@ function Invoke-WPFundoall { $msg = "Please check the tweaks you wish to undo." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return - } - + } + Invoke-WPFRunspace -ArgumentList $Tweaks -ScriptBlock { param($Tweaks) diff --git a/gpedit-home.ps1 b/gpedit-home.ps1 new file mode 100644 index 00000000..da841d33 --- /dev/null +++ b/gpedit-home.ps1 @@ -0,0 +1,4 @@ +Get-ChildItem @( + "C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientTools-Package*.mum", + "C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package*.mum" +) | ForEach-Object { dism.exe /online /norestart /add-package:"$_" } \ No newline at end of file diff --git a/lint/PSScriptAnalyser.ps1 b/lint/PSScriptAnalyser.ps1 index 129f35de..20a9080f 100644 --- a/lint/PSScriptAnalyser.ps1 +++ b/lint/PSScriptAnalyser.ps1 @@ -15,7 +15,7 @@ 'PSShouldProcess', 'PSUseApprovedVerbs', 'PSUseDeclaredVarsMoreThanAssignments') -#> +#> # Do not analyze the following rules. Use ExcludeRules when you have # commented out the IncludeRules settings above and want to include all # the default rules except for those you exclude below. diff --git a/ooshutup10_winutil_settings.cfg b/ooshutup10_winutil_settings.cfg index 7882d7f9..caab9bab 100644 --- a/ooshutup10_winutil_settings.cfg +++ b/ooshutup10_winutil_settings.cfg @@ -1,14 +1,14 @@ ############################################################################ # This file was created with O&O ShutUp10++ V1.9.1435 -# and can be imported onto another computer. +# and can be imported onto another computer. # # Download the application at https://www.oo-software.com/shutup10 -# You can then import the file from within the program. +# You can then import the file from within the program. # # Alternatively you can import it automatically over a command line. -# Simply use the following parameter: +# Simply use the following parameter: # OOSU10.exe -# +# # Selecting the Option /quiet ends the app right after the import and the # user does not get any feedback about the import. # diff --git a/pester/configs.Tests.ps1 b/pester/configs.Tests.ps1 index 85a72f3b..06d560c9 100644 --- a/pester/configs.Tests.ps1 +++ b/pester/configs.Tests.ps1 @@ -1,27 +1,23 @@ -#region Load Variables needed for testing +# Import Config Files +$global:importedconfigs = @{} +Get-ChildItem .\config | Where-Object {$_.Extension -eq ".json"} | ForEach-Object { + $global:importedconfigs[$psitem.BaseName] = Get-Content $psitem.FullName | ConvertFrom-Json +} - #Config Files - $global:importedconfigs = @{} - Get-ChildItem .\config | Where-Object {$_.Extension -eq ".json"} | ForEach-Object { - $global:importedconfigs[$psitem.BaseName] = Get-Content $psitem.FullName | ConvertFrom-Json - } - - -#endregion Load Variables needed for testing #=========================================================================== # Tests - Application Installs #=========================================================================== Describe "Config Files" -ForEach @( - @{ + @{ name = "applications" config = $('{ "winget": "value", "choco": "value" }' | ConvertFrom-Json) }, - @{ + @{ name = "tweaks" undo = $true } @@ -41,7 +37,7 @@ Describe "Config Files" -ForEach @( $result.Add($application) } } - + $result | Select-String "WPF*" | should -BeNullOrEmpty } } @@ -52,16 +48,16 @@ Describe "Config Files" -ForEach @( foreach ($tweak in $tweaks){ $Originals = @( - @{ - name = "registry" + @{ + name = "registry" value = "OriginalValue" }, - @{ - name = "service" + @{ + name = "service" value = "OriginalType" - }, - @{ - name = "ScheduledTask" + }, + @{ + name = "ScheduledTask" value = "OriginalState" } ) diff --git a/pester/functions.Tests.ps1 b/pester/functions.Tests.ps1 index 093abfe2..8a499d24 100644 --- a/pester/functions.Tests.ps1 +++ b/pester/functions.Tests.ps1 @@ -3,23 +3,19 @@ #=========================================================================== Describe "Functions"{ - + Get-ChildItem .\functions -Recurse -File | ForEach-Object { context "$($psitem.BaseName)" { BeforeEach -Scriptblock { . $fullname } - + It "Imports with no errors" -TestCases @{ basename = $($psitem.BaseName) fullname = $psitem.FullName } { Get-ChildItem function:\$basename | should -Not -BeNullOrEmpty - } - It "Contains Description" -TestCases @{ - basename = $($psitem.BaseName) - fullname = $psitem.FullName } { get-help $basename -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Description | should -Not -BeNullOrEmpty } diff --git a/pester/winutil.Tests.ps1 b/pester/winutil.Tests.ps1 index b1752ce6..1077c1f1 100644 --- a/pester/winutil.Tests.ps1 +++ b/pester/winutil.Tests.ps1 @@ -1,15 +1,15 @@ -#region Load Variables needed for testing +# Load Variables needed for testing - ./Compile.ps1 +./Compile.ps1 - $script = Get-Content .\winutil.ps1 - $script[0..($script.count - 21)] | Out-File .\pester.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 -#endregion Load Variables needed for testing - BeforeAll { - . .\pester.ps1 + # Execute the truncated script, bringing the variabes into the current scope + . .\pester.ps1 } Describe "GUI" { @@ -23,5 +23,5 @@ Describe "GUI" { It "Imports with no errors" { $sync.Form | should -Not -BeNullOrEmpty } - } + } } diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 8c2c4bcb..3a536e58 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -1,39 +1,43 @@ # SPDX-License-Identifier: MIT -#Configure max thread count for RunspacePool. +# Set the maximum number of threads for the RunspacePool to the number of threads on the machine $maxthreads = [int]$env:NUMBER_OF_PROCESSORS -#Create a new session state for parsing variables ie hashtable into our runspace. +# Create a new session state for parsing variables into our runspace $hashVars = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync',$sync,$Null $InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() -#Add the variable to the RunspacePool sessionstate +# Add the variable to the session state $InitialSessionState.Variables.Add($hashVars) -#Add functions +# Get every private function and add them to the session state $functions = Get-ChildItem function:\ | Where-Object {$_.name -like "*winutil*" -or $_.name -like "*WPF*"} foreach ($function in $functions){ $functionDefinition = Get-Content function:\$($function.name) $functionEntry = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $($function.name), $functionDefinition - - # And add it to the iss object + $initialSessionState.Commands.Add($functionEntry) } -#Create our runspace pool. We are entering three parameters here min thread count, max thread count and host machine of where these runspaces should be made. -$sync.runspace = [runspacefactory]::CreateRunspacePool(1,$maxthreads,$InitialSessionState, $Host) +# 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 +) -#Open a RunspacePool instance. +# Open the RunspacePool instance $sync.runspace.Open() -#region exception classes +# Create classes for different exceptions class WingetFailedInstall : Exception { [string] $additionalData WingetFailedInstall($Message) : base($Message) {} } - + class ChocoFailedInstall : Exception { [string] $additionalData @@ -45,8 +49,7 @@ $sync.runspace.Open() GenericException($Message) : base($Message) {} } - -#endregion exception classes + $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^ Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed." } @@ -116,7 +118,7 @@ $sync.keys | ForEach-Object { # Setup background config #=========================================================================== -#Load information in the background +# Load computer information in the background Invoke-WPFRunspace -ScriptBlock { $sync.ConfigLoaded = $False @@ -126,25 +128,25 @@ Invoke-WPFRunspace -ScriptBlock { } | Out-Null #=========================================================================== -# Shows the form +# Setup and Show the Form #=========================================================================== +# Print the logo Invoke-WPFFormVariables -try{ - Install-WinUtilChoco -} -Catch [ChocoFailedInstall]{ - Write-Host "===========================================" - Write-Host "-- Chocolatey failed to install ---" - Write-Host "===========================================" -} +# Check if Chocolatey is installed +Install-WinUtilChoco + +# Set the titlebar $sync["Form"].title = $sync["Form"].title + " " + $sync.version +# Set the commands that will run when the form is closed $sync["Form"].Add_Closing({ $sync.runspace.Dispose() $sync.runspace.Close() [System.GC]::Collect() }) +# Show the form $sync["Form"].ShowDialog() | out-null -Stop-Transcript + +Stop-Transcript \ No newline at end of file diff --git a/scripts/start.ps1 b/scripts/start.ps1 index 3e7d803e..2f3f5156 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -8,10 +8,10 @@ Start-Transcript $ENV:TEMP\Winutil.log -Append -#Load DLLs +# Load DLLs Add-Type -AssemblyName System.Windows.Forms -# variable to sync between runspaces +# Variable to sync between runspaces $sync = [Hashtable]::Synchronized(@{}) $sync.PSScriptRoot = $PSScriptRoot $sync.version = "#{replaceme}" diff --git a/winget.ps1 b/winget.ps1 index fd8f64b2..f1ba120a 100644 --- a/winget.ps1 +++ b/winget.ps1 @@ -1,6 +1,6 @@ <#PSScriptInfo -.VERSION 3.0.0 +.VERSION 3.0.1 .GUID 3b581edb-5d90-4fa1-ba15-4f2377275463 @@ -29,6 +29,7 @@ [Version 2.1.0] - Added alternate method/URL for dependencies in case the main URL is down. Fixed licensing issue when winget is installed on Server 2022. [Version 2.1.1] - Switched primary/alternate methods. Added Cleanup function to avoid errors when cleaning up temp files. Added output of URL for alternate method. Suppressed Add-AppxProvisionedPackage output. Improved success message. Improved verbiage. Improve PS script comments. Added check if the URL is empty. Moved display of URL beneath the check. [Version 3.0.0] - Major changes. Added OS version detection checks - detects OS version, release ID, ensures compatibility. Forces older file installation for Server 2022 to avoid issues after installing. Added DebugMode, DisableCleanup, Force. Renamed CheckForUpdates to CheckForUpdate. Improved output. Improved error handling. Improved comments. Improved code readability. Moved CheckForUpdate into function. Added PowerShellGalleryName. Renamed Get-OSVersion to Get-OSInfo. Moved architecture detection into Get-OSInfo. Renamed Get-NewestLink to Get-WingetDownloadUrl. Have Get-WingetDownloadUrl not get preview releases. +[Version 3.0.1] - Updated Get-OSInfo function to fix issues when used on non-English systems. Improved error handling of "resources in use" error. #> @@ -56,7 +57,7 @@ This function should be run with administrative privileges. .PARAMETER Help Displays the full help information for the script. .NOTES - Version : 3.0.0 + Version : 3.0.1 Created by : asheroto .LINK Project Site: https://github.com/asheroto/winget-install @@ -72,7 +73,7 @@ param ( ) # Version -$CurrentVersion = '3.0.0' +$CurrentVersion = '3.0.1' $RepoOwner = 'asheroto' $RepoName = 'winget-install' $PowerShellGalleryName = 'winget-install' @@ -158,12 +159,13 @@ function Get-OSInfo { $nameValue = $osDetails.Caption # Get architecture details of the OS (not the processor) - $architecture = $osDetails.OSArchitecture + # Get only the numbers + $architecture = ($osDetails.OSArchitecture -replace "[^\d]").Trim() # If 32-bit or 64-bit replace with x32 and x64 - if ($architecture -eq "32-bit") { + if ($architecture -eq "32") { $architecture = "x32" - } elseif ($architecture -eq "64-bit") { + } elseif ($architecture -eq "64") { $architecture = "x64" } @@ -624,12 +626,20 @@ function Install-Prerequisite { throw } - Write-Output "URL: ${url}" - Write-Output "`nInstalling ${arch} ${Name}..." + if ($DebugMode) { + Write-Output "URL: ${url}`n" + } + Write-Output "Installing ${arch} ${Name}..." Add-AppxPackage $url -ErrorAction Stop Write-Output "`n$Name installed successfully." } catch { # Alternate method + if ($_.Exception.Message -match '0x80073D02') { + # If resources in use exception, fail immediately + Handle-Error $_ + throw + } + try { $url = $AlternateUrl @@ -758,6 +768,7 @@ if ($CheckForUpdate) { # Heading Write-Output "winget-install $CurrentVersion" +Write-Output "To check for updates, run winget-install -CheckForUpdate" # Set OS version $osVersion = Get-OSInfo @@ -891,7 +902,7 @@ try { if (Get-WingetStatus -eq $true) { Write-Output "winget is installed and working now, you can go ahead and use it." } else { - Write-Warning "winget is installed but is not detected as a command. Try using winget now. If it doesn't work, try restarting your computer." + Write-Warning "winget is installed but is not detected as a command. Try using winget now. If it doesn't work, wait about 1 minute and try again (it is sometimes delayed). Also try restarting your computer." Write-Warning "If you restart your computer and the command still isn't recognized, please read the Troubleshooting section`nof the README: https://github.com/asheroto/winget-install#troubleshooting`n" Write-Warning "Make sure you have the latest version of the script by running this command: $PowerShellGalleryName -CheckForUpdate" } @@ -911,4 +922,4 @@ try { } Write-Warning "Error: $($_.Exception.Message)`n" } -} +} \ No newline at end of file diff --git a/winutil.ps1 b/winutil.ps1 index 2d92c327..5d8da9c9 100755 --- a/winutil.ps1 +++ b/winutil.ps1 @@ -10,18 +10,18 @@ Author : Chris Titus @christitustech Runspace Author: @DeveloperDurp GitHub : https://github.com/ChrisTitusTech - Version : 23.09.23 + Version : 23.10.19 #> Start-Transcript $ENV:TEMP\Winutil.log -Append -#Load DLLs +# Load DLLs Add-Type -AssemblyName System.Windows.Forms -# variable to sync between runspaces +# Variable to sync between runspaces $sync = [Hashtable]::Synchronized(@{}) $sync.PSScriptRoot = $PSScriptRoot -$sync.version = "23.09.23" +$sync.version = "23.10.19" $sync.configs = @{} $sync.ProcessRunning = $false @@ -35,13 +35,19 @@ Function Get-WinUtilCheckBoxes { <# - .DESCRIPTION - Function is meant to find all checkboxes that are checked on the specific tab and input them into a script. + .SYNOPSIS + Finds all checkboxes that are checked on the specific tab and inputs them into a script. - Outputed data will be the names of the checkboxes that were checked + .PARAMETER Group + The group of checkboxes to check - .EXAMPLE + .PARAMETER unCheck + Whether to uncheck the checkboxes that are checked. Defaults to true + .OUTPUTS + A List containing the name of each checked checkbox + + .EXAMPLE Get-WinUtilCheckBoxes "WPFInstall" #> @@ -65,18 +71,18 @@ Function Get-WinUtilCheckBoxes { if ($uncheck -eq $true){ $CheckBox.value.ischecked = $false } - + } } } - + if($Group -eq "WPFTweaks"){ $filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPF*Tweaks*"} $CheckBoxes = $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} Foreach ($CheckBox in $CheckBoxes){ if($CheckBox.value.ischecked -eq $true){ $Output.Add($Checkbox.Name) - + if ($uncheck -eq $true){ $CheckBox.value.ischecked = $false } @@ -90,7 +96,7 @@ Function Get-WinUtilCheckBoxes { Foreach ($CheckBox in $CheckBoxes){ if($CheckBox.value.ischecked -eq $true){ $Output.Add($Checkbox.Name) - + if ($uncheck -eq $true){ $CheckBox.value.ischecked = $false } @@ -102,10 +108,16 @@ Function Get-WinUtilCheckBoxes { } function Get-WinUtilInstallerProcess { <# - - .DESCRIPTION - Meant to check for running processes and will return a boolean response - + + .SYNOPSIS + Checks if the given process is running + + .PARAMETER Process + The process to check + + .OUTPUTS + Boolean - True if the process is running + #> param($Process) @@ -120,15 +132,14 @@ function Get-WinUtilInstallerProcess { } function Get-WinUtilRegistry { <# - - .DESCRIPTION - This function will make all modifications to the registry - .EXAMPLE + .SYNOPSIS + Gets the value of a registry key - Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" - - #> + .EXAMPLE + Get-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" + + #> param ( $Name, $Path, @@ -136,7 +147,7 @@ function Get-WinUtilRegistry { $Value ) - Try{ + Try{ $syscheckvalue = Get-ItemPropertyValue -Path $Path -Value $Value # Return Value } @@ -153,13 +164,16 @@ function Get-WinUtilRegistry { } Function Get-WinUtilToggleStatus { <# - - .DESCRIPTION - Meant to pull the registry keys for a toggle switch and returns true or false - True should mean status is enabled - False should mean status is disabled - + .SYNOPSIS + Pulls the registry keys for the given toggle switch and checks whether the toggle should be checked or unchecked + + .PARAMETER ToggleSwitch + The name of the toggle to check + + .OUTPUTS + Boolean to set the toggle's status to + #> Param($ToggleSwitch) @@ -168,7 +182,7 @@ Function Get-WinUtilToggleStatus { $system = (Get-ItemProperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize').SystemUsesLightTheme if($app -eq 0 -and $system -eq 0){ return $true - } + } else{ return $false } @@ -177,7 +191,7 @@ Function Get-WinUtilToggleStatus { $bingsearch = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search').BingSearchEnabled if($bingsearch -eq 0){ return $false - } + } else{ return $true } @@ -186,10 +200,13 @@ Function Get-WinUtilToggleStatus { function Get-WinUtilVariables { <# - - .DESCRIPTION - placeholder - + + .SYNOPSIS + Gets every form object of the provided type + + .OUTPUTS + List containing every object that matches the provided type + #> param ( [Parameter()] @@ -197,7 +214,7 @@ function Get-WinUtilVariables { [string]$Type ) - $keys = $sync.keys | Where-Object {$psitem -like "WPF*"} + $keys = $sync.keys | Where-Object {$psitem -like "WPF*"} if($type){ $output = $keys | ForEach-Object { @@ -208,49 +225,55 @@ function Get-WinUtilVariables { } 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 } function Install-WinUtilChoco { <# - - .DESCRIPTION - Function is meant to ensure Choco is installed - + + .SYNOPSIS + Installs Chocolatey if it is not already installed + #> - 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?" - #Let user decide if he wants 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 - } + + 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 + } - Catch{ - throw [ChocoFailedInstall]::new('Failed to install') + Catch { + Write-Host "===========================================" + Write-Host "-- Chocolatey failed to install ---" + Write-Host "===========================================" } } Function Install-WinUtilProgramWinget { <# - - .DESCRIPTION - This will install programs via Winget using a new powershell.exe instance to prevent the GUI from locking up. - Note the triple quotes are required any time you need a " in a normal script block. - + .SYNOPSIS + Manages the provided programs using Winget + + .PARAMETER ProgramsToInstall + A list of programs to manage + + .PARAMETER manage + The action to perform on the programs, can be either 'Installing' or 'Uninstalling' + + .NOTES + The triple quotes are required any time you need a " in a normal script block. + #> param( @@ -264,7 +287,7 @@ Function Install-WinUtilProgramWinget { Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0 Foreach ($Program in $($ProgramsToInstall -split ",")){ - + Write-Progress -Activity "$manage Applications" -Status "$manage $Program $($x + 1) of $count" -PercentComplete $($x/$count*100) if($manage -eq "Installing"){ Start-Process -FilePath winget -ArgumentList "install -e --accept-source-agreements --accept-package-agreements --silent $Program" -NoNewWindow -Wait @@ -272,7 +295,7 @@ Function Install-WinUtilProgramWinget { if($manage -eq "Uninstalling"){ Start-Process -FilePath winget -ArgumentList "uninstall -e --purge --force --silent $Program" -NoNewWindow -Wait } - + $X++ } @@ -281,30 +304,30 @@ Function Install-WinUtilProgramWinget { } 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 - } +} function Install-WinUtilWinget { - + <# - - .DESCRIPTION - Function is meant to ensure winget is installed - + + .SYNOPSIS + Installs Winget if it is not already installed + #> Try{ Write-Host "Checking if Winget is Installed..." if (Test-WinUtilPackageManager -winget) { - #Checks if winget executable exists and if the Windows Version is 1809 or higher + # Checks if winget executable exists and if the Windows Version is 1809 or higher Write-Host "Winget Already Installed" return } - #Gets the computer's information + # Gets the computer's information if ($null -eq $sync.ComputerInfo){ $ComputerInfo = Get-ComputerInfo -ErrorAction Stop } @@ -313,14 +336,14 @@ function Install-WinUtilWinget { } if (($ComputerInfo.WindowsVersion) -lt "1809") { - #Checks if Windows Version is too old for winget + # Checks if Windows Version is too old for winget Write-Host "Winget is not supported on this version of Windows (Pre-1809)" return } Write-Host "Running Alternative Installer and Direct Installing" - Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "irm https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/winget.ps1 | iex" - + Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget" + Write-Host "Winget Installed" } Catch{ @@ -328,11 +351,14 @@ function Install-WinUtilWinget { } } function Invoke-WinUtilBingSearch { - <# - - .DESCRIPTION - Sets Bing Search on or off - + <# + + .SYNOPSIS + Disables/Enables Bing Search + + .PARAMETER Enabled + Indicates whether to enable or disable Bing Search + #> Param($Enabled) Try{ @@ -362,13 +388,10 @@ Function Invoke-WinUtilCurrentSystem { <# - .DESCRIPTION - Function is meant to read existing system registry and check according configuration. - - Example: Is telemetry enabled? check the box. - - .EXAMPLE + .SYNOPSIS + Checks to see what tweaks have already been applied and what programs are installed, and checks the according boxes + .EXAMPLE Get-WinUtilCheckBoxes "WPFInstall" #> @@ -406,19 +429,19 @@ Function Invoke-WinUtilCurrentSystem { $registryKeys = $sync.configs.tweaks.$Config.registry $scheduledtaskKeys = $sync.configs.tweaks.$Config.scheduledtask $serviceKeys = $sync.configs.tweaks.$Config.service - + if($registryKeys -or $scheduledtaskKeys -or $serviceKeys){ $Values = @() Foreach ($tweaks in $registryKeys){ Foreach($tweak in $tweaks){ - + if(test-path $tweak.Path){ $actualValue = Get-ItemProperty -Name $tweak.Name -Path $tweak.Path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $($tweak.Name) $expectedValue = $tweak.Value if ($expectedValue -notlike $actualValue){ - $values += $False + $values += $False } } } @@ -427,7 +450,7 @@ Function Invoke-WinUtilCurrentSystem { Foreach ($tweaks in $scheduledtaskKeys){ Foreach($tweak in $tweaks){ $task = $ScheduledTasks | Where-Object {$($psitem.TaskPath + $psitem.TaskName) -like "\$($tweak.name)"} - + if($task){ $actualValue = $task.State $expectedValue = $tweak.State @@ -441,7 +464,7 @@ Function Invoke-WinUtilCurrentSystem { Foreach ($tweaks in $serviceKeys){ Foreach($tweak in $tweaks){ $Service = Get-Service -Name $tweak.Name - + if($Service){ $actualValue = $Service.StartType $expectedValue = $tweak.StartupType @@ -461,11 +484,14 @@ Function Invoke-WinUtilCurrentSystem { } Function Invoke-WinUtilDarkMode { - <# - - .DESCRIPTION - Sets Dark Mode on or off - + <# + + .SYNOPSIS + Enables/Disables Dark Mode + + .PARAMETER DarkMoveEnabled + Indicates the current dark mode state + #> Param($DarkMoveEnabled) Try{ @@ -477,7 +503,7 @@ Function Invoke-WinUtilDarkMode { Write-Host "Disabling Dark Mode" $DarkMoveValue = 1 } - + $Theme = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" Set-ItemProperty -Path $Theme -Name AppsUseLightTheme -Value $DarkMoveValue Set-ItemProperty -Path $Theme -Name SystemUsesLightTheme -Value $DarkMoveValue @@ -495,10 +521,10 @@ Function Invoke-WinUtilDarkMode { } function Invoke-WinUtilFeatureInstall { <# - - .DESCRIPTION - This function converts all the values from the tweaks.json and routes them to the appropriate function - + + .SYNOPSIS + Converts all the values from the tweaks.json and routes them to the appropriate function + #> param( @@ -508,7 +534,7 @@ function Invoke-WinUtilFeatureInstall { $CheckBox | ForEach-Object { if($sync.configs.feature.$psitem.feature){ Foreach( $feature in $sync.configs.feature.$psitem.feature ){ - Try{ + Try{ Write-Host "Installing $feature" Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart } @@ -519,10 +545,10 @@ function Invoke-WinUtilFeatureInstall { else{ Write-Warning "Unable to Install $feature due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } - } + } } if($sync.configs.feature.$psitem.InvokeScript){ Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ){ @@ -539,24 +565,29 @@ function Invoke-WinUtilFeatureInstall { else{ Write-Warning "Unable to Install $feature due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } - } + } } } } function Invoke-WinUtilScript { <# - - .DESCRIPTION - This function will run a separate powershell script. Meant for things that can't be handled with the other functions - .EXAMPLE + .SYNOPSIS + Invokes the provided scriptblock. Intended for things that can't be handled with the other functions. + .PARAMETER Name + The name of the scriptblock being invoked + + .PARAMETER scriptblock + The scriptblock to be invoked + + .EXAMPLE $Scriptblock = [scriptblock]::Create({"Write-output 'Hello World'"}) Invoke-WinUtilScript -ScriptBlock $scriptblock -Name "Hello World" - + #> param ( $Name, @@ -586,16 +617,22 @@ function Invoke-WinUtilScript { Catch { # Generic catch block to handle any other type of exception Write-Warning "Unable to run script for $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } - + } function Invoke-WinUtilTweaks { <# - - .DESCRIPTION - This function converts all the values from the tweaks.json and routes them to the appropriate function - + + .SYNOPSIS + Invokes the function associated with each provided checkbox + + .PARAMETER CheckBox + The checkbox to invoke + + .PARAMETER undo + Indicates whether to undo the operation contained in the checkbox + #> param( @@ -610,7 +647,7 @@ function Invoke-WinUtilTweaks { ScriptType = "UndoScript" } - } + } Else{ $Values = @{ Registry = "Value" @@ -652,14 +689,16 @@ function Invoke-WinUtilTweaks { } function Remove-WinUtilAPPX { <# - - .DESCRIPTION - This function will remove any of the provided APPX names - .EXAMPLE + .SYNOPSIS + Removes all APPX packages that match the given name + .PARAMETER Name + The name of the APPX package to remove + + .EXAMPLE Remove-WinUtilAPPX -Name "Microsoft.Microsoft3DViewer" - + #> param ( $Name @@ -676,24 +715,26 @@ function Remove-WinUtilAPPX { } Else{ Write-Warning "Unable to uninstall $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } Catch{ Write-Warning "Unable to uninstall $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } function Set-WinUtilDNS { <# - - .DESCRIPTION - This function will set the DNS of all interfaces that are in the "Up" state. It will lookup the values from the DNS.Json file - .EXAMPLE + .SYNOPSIS + Sets the DNS of all interfaces that are in the "Up" state. It will lookup the values from the DNS.Json file + .PARAMETER DNSProvider + The DNS provider to set the DNS server to + + .EXAMPLE Set-WinUtilDNS -DNSProvider "google" - + #> param($DNSProvider) if($DNSProvider -eq "Default"){return} @@ -713,20 +754,31 @@ function Set-WinUtilDNS { } Catch{ Write-Warning "Unable to set DNS Provider due to an unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } function Set-WinUtilRegistry { <# - - .DESCRIPTION - This function will make all modifications to the registry - .EXAMPLE + .SYNOPSIS + Modifies the registry based on the given inputs + .PARAMETER Name + The name of the key to modify + + .PARAMETER Path + The path to the key + + .PARAMETER Type + The type of value to set the key to + + .PARAMETER Value + The value to set the key to + + .EXAMPLE Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0" - - #> + + #> param ( $Name, $Path, @@ -734,7 +786,7 @@ function Set-WinUtilRegistry { $Value ) - Try{ + Try{ if(!(Test-Path 'HKU:\')){New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS} If (!(Test-Path $Path)) { @@ -758,11 +810,11 @@ function Set-WinUtilRegistry { } function Set-WinUtilRestorePoint { <# - - .DESCRIPTION - This function will make a Restore Point - #> + .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)) { @@ -782,7 +834,7 @@ function Set-WinUtilRestorePoint { $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 + 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 @@ -791,21 +843,26 @@ function Set-WinUtilRestorePoint { # 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" } } function Set-WinUtilScheduledTask { <# - - .DESCRIPTION - This function will enable/disable the provided Scheduled Task - .EXAMPLE + .SYNOPSIS + Enables/Disables the provided Scheduled Task + .PARAMETER Name + The path to the Scheduled Task + + .PARAMETER State + The State to set the Task to + + .EXAMPLE Set-WinUtilScheduledTask -Name "Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -State "Disabled" - + #> param ( $Name, @@ -833,30 +890,35 @@ function Set-WinUtilScheduledTask { } Catch{ Write-Warning "Unable to run script for $name due to unhandled exception" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } } Function Set-WinUtilService { <# - - .DESCRIPTION - This function will change the startup type of services and start/stop them as needed - .EXAMPLE + .SYNOPSIS + Changes the startup type of the given service + .PARAMETER Name + The name of the service to modify + + .PARAMETER StartupType + The startup type to set the service to + + .EXAMPLE Set-WinUtilService -Name "HomeGroupListener" -StartupType "Manual" - - #> + + #> param ( $Name, $StartupType ) try { Write-Host "Setting Service $Name to $StartupType" - + # Check if the service exists $service = Get-Service -Name $Name -ErrorAction Stop - + # Service exists, proceed with changing properties $service | Set-Service -StartupType $StartupType -ErrorAction Stop } @@ -867,18 +929,23 @@ Function Set-WinUtilService { Write-Warning "Unable to set $Name due to unhandled exception" Write-Warning $_.Exception.Message } - + } function Set-WinUtilUITheme { <# - - .DESCRIPTION - This function will set theme to the XAML file - .EXAMPLE + .SYNOPSIS + Sets the theme of the XAML file + .PARAMETER inputXML + A string representing the XAML object to modify + + .PARAMETER themeName + The name of the theme to set the XAML to. Defaults to 'matrix' + + .EXAMPLE Set-WinUtilUITheme -inputXAML $inputXAML - + #> param ( @@ -912,17 +979,23 @@ function Set-WinUtilUITheme { } catch { Write-Warning "Unable to apply theme" - Write-Warning $psitem.Exception.StackTrace + Write-Warning $psitem.Exception.StackTrace } return $inputXML; } function Test-WinUtilPackageManager { <# - - .DESCRIPTION - Checks for Winget or Choco depending on the parameter - + + .SYNOPSIS + Checks if Winget and/or Choco are installed + + .PARAMETER winget + Check if Winget is installed + + .PARAMETER choco + Check if Chocolatey is installed + #> Param( @@ -947,10 +1020,10 @@ function Test-WinUtilPackageManager { Function Update-WinUtilProgramWinget { <# - - .DESCRIPTION - This will update programs via Winget using a new powershell.exe instance to prevent the GUI from locking up. - + + .SYNOPSIS + This will update all programs using Winget + #> [ScriptBlock]$wingetinstall = { @@ -969,17 +1042,18 @@ Function Update-WinUtilProgramWinget { function Invoke-WPFButton { <# - - .DESCRIPTION - Meant to make creating buttons easier. There is a section below in the gui that will assign this function to every button. - This way you can dictate what each button does from this function. - - Input will be the name of the button that is clicked. - #> - - Param ([string]$Button) - #Use this to get the name of the button + .SYNOPSIS + Invokes the function associated with the clicked button + + .PARAMETER Button + The name of the button that was clicked + + #> + + 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") Switch -Wildcard ($Button){ @@ -1023,11 +1097,14 @@ function Invoke-WPFButton { } } function Invoke-WPFControlPanel { - <# - - .DESCRIPTION - Simple Switch for legacy windows - + <# + + .SYNOPSIS + Opens the requested legacy panel + + .PARAMETER Panel + The panel to open + #> param($Panel) @@ -1042,11 +1119,11 @@ function Invoke-WPFControlPanel { } } function Invoke-WPFFeatureInstall { - <# - - .DESCRIPTION - GUI Function to install Windows Features - + <# + + .SYNOPSIS + Installs selected Windows Features + #> if($sync.ProcessRunning){ @@ -1069,26 +1146,30 @@ function Invoke-WPFFeatureInstall { Write-Host "--- Features are Installed ---" Write-Host "--- A Reboot may be required ---" Write-Host "===================================" - + $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "All features are now installed " $Messageboxbody = ("Done") $MessageIcon = [System.Windows.MessageBoxImage]::Information - + [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) } } function Invoke-WPFFixesNetwork { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Resets various network configurations + #> Write-Host "Resetting Network with netsh" + + # Reset WinSock catalog to a clean state Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winsock", "reset" + # Resets WinHTTP proxy setting to DIRECT Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winhttp", "reset", "proxy" + # Removes all user configured IP settings Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "int", "ip", "reset" Write-Host "Process complete. Please reboot your computer." @@ -1099,20 +1180,20 @@ function Invoke-WPFFixesNetwork { $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) - Write-Host "=================================" - Write-Host "-- Reset Network Configuration --" - Write-Host "=================================" + Write-Host "==========================================" + Write-Host "-- Network Configuration has been Reset --" + Write-Host "==========================================" } function Invoke-WPFFixesUpdate { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Performs various tasks in an attempt to repair Windows Update + #> - ### Reset Windows Update Script - reregister dlls, services, and remove registry entries. + # Reset Windows Update Script - reregister dlls, services, and remove registry entries Write-Host "1. Stopping Windows Update Services..." Stop-Service -Name BITS Stop-Service -Name wuauserv @@ -1188,16 +1269,16 @@ Write-Host "12) Forcing discovery..." $MessageIcon = [System.Windows.MessageBoxImage]::Information [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) - Write-Host "=================================" - Write-Host "-- Reset ALL Updates to Factory -" - Write-Host "=================================" + Write-Host "===============================================" + Write-Host "-- Reset All Windows Update Settings to Stock -" + Write-Host "===============================================" } Function Invoke-WPFFormVariables { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Prints the logo + #> #If ($global:ReadmeDisplay -ne $true) { Write-Host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow; $global:ReadmeDisplay = $true } @@ -1232,8 +1313,11 @@ Function Invoke-WPFFormVariables { function Invoke-WPFGetInstalled { <# - .DESCRIPTION - placeholder + .SYNOPSIS + Invokes the function that gets the checkboxes to check in a new runspace + + .PARAMETER checkbox + Indicates whether to check for installed 'winget' programs or applied 'tweaks' #> param($checkbox) @@ -1262,9 +1346,9 @@ function Invoke-WPFGetInstalled { if($checkbox -eq "tweaks"){ Write-Host "Getting Installed Tweaks..." } - + $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox - + $sync.form.Dispatcher.invoke({ foreach($checkbox in $Checkboxes){ $sync.$checkbox.ischecked = $True @@ -1277,14 +1361,19 @@ function Invoke-WPFGetInstalled { } function Invoke-WPFImpex { <# - - .DESCRIPTION - This function handles importing and exporting of the checkboxes checked for the tweaks section - .EXAMPLE + .SYNOPSIS + Handles importing and exporting of the checkboxes checked for the tweaks section + .PARAMETER type + Indicates whether to 'import' or 'export' + + .PARAMETER checkbox + The checkbox to export to a file or apply the imported file to + + .EXAMPLE Invoke-WPFImpex -type "export" - + #> param( $type, @@ -1295,7 +1384,7 @@ function Invoke-WPFImpex { $FileBrowser = New-Object System.Windows.Forms.SaveFileDialog } if ($type -eq "import"){ - $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog + $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog } $FileBrowser.InitialDirectory = [Environment]::GetFolderPath('Desktop') @@ -1305,7 +1394,7 @@ function Invoke-WPFImpex { if($FileBrowser.FileName -eq ""){ return } - + if ($type -eq "export"){ $jsonFile = Get-WinUtilCheckBoxes $checkbox -unCheck $false $jsonFile | ConvertTo-Json | Out-File $FileBrowser.FileName -Force @@ -1317,10 +1406,10 @@ function Invoke-WPFImpex { } function Invoke-WPFInstall { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Installs the selected programs using winget + #> if($sync.ProcessRunning){ @@ -1345,14 +1434,14 @@ function Invoke-WPFInstall { # Ensure winget is installed Install-WinUtilWinget - # Install all winget programs in new window + # 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 "===========================================" @@ -1369,10 +1458,10 @@ function Invoke-WPFInstall { } function Invoke-WPFInstallUpgrade { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Invokes the function that upgrades all installed programs using winget + #> if(!(Test-WinUtilPackageManager -winget)){ Write-Host "===========================================" @@ -1396,20 +1485,37 @@ function Invoke-WPFInstallUpgrade { } function Invoke-WPFPanelAutologin { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Enables autologin using Sysinternals Autologon.exe + #> curl.exe -ss "https://live.sysinternals.com/Autologon.exe" -o $env:temp\autologin.exe # Official Microsoft recommendation https://learn.microsoft.com/en-us/sysinternals/downloads/autologon cmd /c $env:temp\autologin.exe /accepteula } function Invoke-WPFPanelDISM { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Checks for system corruption using Chkdsk, SFC, and DISM + + .DESCRIPTION + 1. Chkdsk - Fixes disk and filesystem corruption + 2. SFC Run 1 - Fixes system file corruption, and fixes DISM if it was corrupted + 3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted + 4. SFC Run 2 - Fixes system file corruption, this time with an almost guaranteed uncorrupted system image + + .NOTES + Command Arguments: + 1. Chkdsk + /Scan - Runs an online scan on the system drive, attempts to fix any corruption, and queues other corruption for fixing on reboot + 2. SFC + /ScanNow - Performs a scan of the system files and fixes any corruption + 3. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted + /Online - Fixes the currently running system image + /Cleanup-Image - Performs cleanup operations on the image, could remove some unneeded temporary files + /Restorehealth - Performs a scan of the image and fixes any corruption + #> Start-Process PowerShell -ArgumentList "Write-Host '(1/4) Chkdsk' -ForegroundColor Green; Chkdsk /scan; Write-Host '`n(2/4) SFC - 1st scan' -ForegroundColor Green; sfc /scannow; @@ -1420,8 +1526,17 @@ function Invoke-WPFPanelDISM { function Invoke-WPFPresets { <# - .DESCRIPTION - Meant to make settings presets easier in the tweaks tab. Will pull the data from config/preset.json + .SYNOPSIS + Sets the options in the tweaks panel to the given preset + + .PARAMETER preset + The preset to set the options to + + .PARAMETER imported + If the preset is imported from a file, defaults to false + + .PARAMETER checkbox + The checkbox to set the options to, defaults to 'WPFTweaks' #> @@ -1461,40 +1576,41 @@ function Invoke-WPFPresets { function Invoke-WPFRunspace { <# - - .DESCRIPTION - Simple function to make it easier to invoke a runspace from inside the script. - .EXAMPLE + .SYNOPSIS + Creates and invokes a runspace using the given scriptblock and argumentlist - $params = @{ - ScriptBlock = $sync.ScriptsInstallPrograms - ArgumentList = "Installadvancedip,Installbitwarden" - Verbose = $true - } + .PARAMETER ScriptBlock + The scriptblock to invoke in the runspace + + .PARAMETER ArgumentList + A list of arguments to pass to the runspace + + .EXAMPLE + Invoke-WPFRunspace ` + -ScriptBlock $sync.ScriptsInstallPrograms ` + -ArgumentList "Installadvancedip,Installbitwarden" ` - Invoke-WPFRunspace @params - #> [CmdletBinding()] Param ( $ScriptBlock, $ArgumentList - ) + ) - #Crate a PowerShell instance. + # Create a PowerShell instance $script:powershell = [powershell]::Create() - #Add Scriptblock and Arguments to runspace + # Add Scriptblock and Arguments to runspace $script:powershell.AddScript($ScriptBlock) $script:powershell.AddArgument($ArgumentList) $script:powershell.RunspacePool = $sync.runspace - - #Run our RunspacePool. + + # Execute the RunspacePool $script:handle = $script:powershell.BeginInvoke() - #Cleanup our RunspacePool threads when they are complete ie. GC. + # Clean up the RunspacePool threads when they are complete, and invoke the garbage collector to clean up the memory if ($script:handle.IsCompleted) { $script:powershell.EndInvoke($script:handle) @@ -1507,15 +1623,18 @@ function Invoke-WPFRunspace { function Invoke-WPFShortcut { <# - .DESCRIPTION - Creates a shortcut + .SYNOPSIS + Creates a shortcut and prompts for a save location + + .PARAMETER ShortcutToAdd + The name of the shortcut to add #> param($ShortcutToAdd) Switch ($ShortcutToAdd) { "WinUtil" { - $SourceExe = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" + $SourceExe = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" $IRM = 'irm https://christitus.com/win | iex' $Powershell = '-ExecutionPolicy Bypass -Command "Start-Process powershell.exe -verb runas -ArgumentList' $ArgumentsToSourceExe = "$powershell '$IRM'" @@ -1534,16 +1653,19 @@ function Invoke-WPFShortcut { $Shortcut.TargetPath = $SourceExe $Shortcut.Arguments = $ArgumentsToSourceExe $Shortcut.Save() - + Write-Host "Shortcut for $ShortcutToAdd has been saved to $($FileBrowser.FileName)" } function Invoke-WPFTab { <# - - .DESCRIPTION - Sole purpose of this function is to reduce duplicated code for switching between tabs. - + + .SYNOPSIS + Sets the selected tab to the tab that was clicked + + .PARAMETER ClickedTab + The name of the tab that was clicked + #> Param ($ClickedTab) @@ -1552,7 +1674,7 @@ function Invoke-WPFTab { $x = [int]($ClickedTab -replace "WPFTab","" -replace "BT","") - 1 0..($Tabs.Count -1 ) | ForEach-Object { - + if ($x -eq $psitem){ $sync.$TabNav.Items[$psitem].IsSelected = $true } @@ -1564,17 +1686,18 @@ function Invoke-WPFTab { function Invoke-WPFToggle { <# - - .DESCRIPTION - Meant to make creating toggle switches easier. There is a section below in the gui that will assign this function to every switch. - This way you can dictate what each button does from this function. - - Input will be the name of the toggle that is checked. - #> - - Param ([string]$Button) - #Use this to get the name of the button + .SYNOPSIS + Invokes the scriptblock for the given toggle + + .PARAMETER Button + The name of the toggle to invoke + + #> + + 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") Switch -Wildcard ($Button){ @@ -1586,10 +1709,10 @@ function Invoke-WPFToggle { } function Invoke-WPFtweaksbutton { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Invokes the functions associated with each group of checkboxes + #> if($sync.ProcessRunning){ @@ -1608,13 +1731,13 @@ function Invoke-WPFtweaksbutton { return } - Set-WinUtilRestorePoint - Invoke-WPFRunspace -ArgumentList $Tweaks -ScriptBlock { param($Tweaks) $sync.ProcessRunning = $true + Set-WinUtilRestorePoint + Foreach ($tweak in $tweaks){ Invoke-WinUtilTweaks $tweak } @@ -1634,47 +1757,52 @@ function Invoke-WPFtweaksbutton { } Function Invoke-WPFUltimatePerformance { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Creates or removes the Ultimate Performance power scheme + + .PARAMETER State + Indicates whether to enable or disable the Ultimate Performance power scheme + #> param($State) Try{ if($state -eq "Enabled"){ - # Define the name and GUID of the power scheme you want to add + # Define the name and GUID of the power scheme $powerSchemeName = "Ultimate Performance" $powerSchemeGuid = "e9a42b02-d5df-448d-aa00-03f14749eb61" # Get all power schemes $schemes = powercfg /list | Out-String -Stream - # Find the scheme you want to add + # Check if the power scheme already exists $ultimateScheme = $schemes | Where-Object { $_ -match $powerSchemeName } - # If the scheme does not exist, add it if ($null -eq $ultimateScheme) { Write-Host "Power scheme '$powerSchemeName' not found. Adding..." # Add the power scheme powercfg /duplicatescheme $powerSchemeGuid powercfg -attributes SUB_SLEEP 7bc4a2f9-d8fc-4469-b07b-33eb785aaca0 -ATTRIB_HIDE + powercfg -setactive $powerSchemeGuid + powercfg -change -monitor-timeout-ac 0 + Write-Host "Power scheme added successfully." } else { Write-Host "Power scheme '$powerSchemeName' already exists." - } + } } elseif($state -eq "Disabled"){ - # Define the name of the power scheme you want to remove + # Define the name of the power scheme $powerSchemeName = "Ultimate Performance" # Get all power schemes $schemes = powercfg /list | Out-String -Stream - # Find the scheme you want to remove + # Find the scheme to be removed $ultimateScheme = $schemes | Where-Object { $_ -match $powerSchemeName } # If the scheme exists, remove it @@ -1684,10 +1812,10 @@ Function Invoke-WPFUltimatePerformance { if($null -ne $guid){ Write-Host "Found power scheme '$powerSchemeName' with GUID $guid. Removing..." - + # Remove the power scheme powercfg /delete $guid - + Write-Host "Power scheme removed successfully." } else { @@ -1699,7 +1827,7 @@ Function Invoke-WPFUltimatePerformance { } } - + } Catch{ Write-Warning $psitem.Exception.Message @@ -1707,10 +1835,10 @@ Function Invoke-WPFUltimatePerformance { } function Invoke-WPFundoall { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Undoes every selected tweak + #> if($sync.ProcessRunning){ @@ -1725,8 +1853,8 @@ function Invoke-WPFundoall { $msg = "Please check the tweaks you wish to undo." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return - } - + } + Invoke-WPFRunspace -ArgumentList $Tweaks -ScriptBlock { param($Tweaks) @@ -1903,14 +2031,14 @@ function Invoke-WPFundoall { } function Invoke-WPFUnInstall { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Uninstalls the selected programs + #> if($sync.ProcessRunning){ - $msg = "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 } @@ -1925,7 +2053,7 @@ function Invoke-WPFUnInstall { $ButtonType = [System.Windows.MessageBoxButton]::YesNo $MessageboxTitle = "Are you sure?" - $Messageboxbody = ("This will uninstall the following applications `n $WingetInstall") + $Messageboxbody = ("This will uninstall the following applications: `n $WingetInstall") $MessageIcon = [System.Windows.MessageBoxImage]::Information $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) @@ -1937,23 +2065,23 @@ function Invoke-WPFUnInstall { try{ $sync.ProcessRunning = $true - # Install all winget programs in new window + # Install all selected programs in new window Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall -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) Write-Host "===========================================" - Write-Host "-- Uninstalls have finished ---" + Write-Host "-- Uninstalls have finished ---" Write-Host "===========================================" } Catch { Write-Host "===========================================" - Write-Host "-- Winget failed to install ---" + Write-Host "-- Winget failed to install ---" Write-Host "===========================================" } $sync.ProcessRunning = $False @@ -1961,10 +2089,10 @@ function Invoke-WPFUnInstall { } function Invoke-WPFUpdatesdefault { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Resets Windows Update settings to default + #> If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null @@ -2000,16 +2128,19 @@ function Invoke-WPFUpdatesdefault { Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "BranchReadinessLevel" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferFeatureUpdatesPeriodInDays" -ErrorAction SilentlyContinue Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferQualityUpdatesPeriodInDays" -ErrorAction SilentlyContinue - Write-Host "=================================" - Write-Host "--- Updates Set to Default ---" - Write-Host "=================================" + Write-Host "===================================================" + Write-Host "--- Windows Update Settings Reset to Default ---" + Write-Host "===================================================" } function Invoke-WPFUpdatesdisable { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Disables Windows Update + + .NOTES + Disabling Windows Update is not recommended. This is only for advanced users who know what they are doing. + #> If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null @@ -2033,15 +2164,22 @@ function Invoke-WPFUpdatesdisable { Get-Service -Name $service -ErrorAction SilentlyContinue | Set-Service -StartupType Disabled } Write-Host "=================================" - Write-Host "--- Updates ARE DISABLED ---" + Write-Host "--- Updates ARE DISABLED ---" Write-Host "=================================" } function Invoke-WPFUpdatessecurity { <# - - .DESCRIPTION - PlaceHolder - + + .SYNOPSIS + Sets Windows Update to recommended settings + + .DESCRIPTION + 1. Disables driver offering through Windows Update + 2. Disables Windows Update automatic restart + 3. Sets Windows Update to Semi-Annual Channel (Targeted) + 4. Defers feature updates for 365 days + 5. Defers quality updates for 4 days + #> Write-Host "Disabling driver offering through Windows Update..." If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata")) { @@ -2092,7 +2230,7 @@ $inputXML = ' - + + +