Compare commits

...
18 Commits
Author SHA1 Message Date
Paweł GwozdowskiandGitHub 157a66b14d Update Invoke-WPFUIElements.ps1 (#4824) 2026-07-13 13:20:53 -05:00
9791386f53 fix: resolve silent failures in AppX removal and PS7 DISM bugs (#4822)
* fix: resolve silent failures in AppX removal and PS7 DISM bugs

- Fixed a bug where Remove-AppxPackage failed silently in PowerShell 7 due to pipeline binding issues. We now explicitly loop through Get-AppxPackage results and pass PackageFullName directly.
- Added wildcard matching to Get-AppxPackage and Get-AppxProvisionedPackage to reliably locate packages regardless of short name vs family name variations.
- Offloaded Get-AppxProvisionedPackage and Remove-AppxProvisionedPackage execution to Windows PowerShell 5.1 (powershell.exe) to bypass PowerShell 7 DISM COM exceptions ("Class not registered") and performance hangs.
- Deduplicated AppX removal logic by calling Remove-WinUtilAPPX directly from Invoke-WPFAppxRemoval instead of copying the implementation.

* refactor(Remove-WinUtilAPPX): use script block to improve readability

* feat: enhance AppX removal process and add provisioned package removal function

* fix(tests): update AppX removal tests

This also adds tests for the new Remove-WinUtilProvisionedAPPX functionality

* Move AppX removal under Tweaks

* Address AppX removal review feedback

* Complete AppX removal error handling

* Prevent AppX cleanup confirmation prompts

---------

Co-authored-by: Chris Titus <contact@christitus.com>
2026-07-13 13:16:35 -05:00
Chris TitusandGitHub c8e756dc11 chore: Update generated dev docs (#4838) 2026-07-13 11:40:20 -05:00
Sean (ANGRYxScotsman)andGitHub 9e21c8f4a7 Updated ConsumerFeatures description and small dev doc edit (#4817)
* Update tweaks.json

* Update _index.md

* Update _index.md
2026-07-13 11:39:49 -05:00
Chris TitusandGitHub 8cd8679512 chore: Update generated dev docs (#4837) 2026-07-13 11:37:52 -05:00
ac11c73b64 feat(legacy-panels): add Firewall, Security, Programs, and Mouse to L… (#4809)
* feat(legacy-panels): add Firewall, Security, Programs, and Mouse to Legacy Windows Panels

- Added `firewall.cpl`, `wscui.cpl`, `appwiz.cpl`, and `main.cpl` to `config/feature.json`

* chore(legacy-panels): alphabetize panel entries

---------

Co-authored-by: Chris Titus <contact@christitus.com>
2026-07-13 11:37:22 -05:00
KarimandGitHub 9d67514bf9 feat(apps): add gsudo (#4810)
- Added gsudo to the Pro Tools category to provide a native sudo equivalent for Windows terminals.
2026-07-13 10:26:44 -05:00
Chris TitusandGitHub fea9f4e869 chore: Update generated dev docs (#4836) 2026-07-13 10:26:33 -05:00
1aa0dd90ef prevent-automatic-download-of-applications-associated-with-device-metadata (#4827)
* add tweak

* add devdocs

* add devdocs

---------

Co-authored-by: matthewkasiski <matt@matthewkasiski.me>
2026-07-13 10:25:58 -05:00
Yayo RazoandGitHub 90a19685f5 fix(install): use correctly-scoped $app instead of undefined $Apps in app entry rendering (#4834) 2026-07-13 04:23:24 -05:00
007995c112 Improve install app card UI (#4771)
Co-authored-by: Chris Titus <contact@christitus.com>
2026-07-11 11:21:59 -05:00
Chris Titus 0dcd361c51 Remove slash commands for contributors 2026-07-09 14:25:50 -05:00
eduardodepaivaandGitHub aeaef46e30 Fix names in applications.json. (#4819) 2026-07-08 10:25:15 -05:00
Ivan LepekhaandGitHub e0dfeb4f4d Remove Lightshot entry from applications.json (#4808)
Removed Lightshot application entry from applications.json
2026-07-04 09:52:55 -05:00
Chris Titus 1c7ee06bbe chore: skip automated updates in changelog 2026-07-04 00:58:24 -05:00
ed6de94c46 Update sponsors in README (#4544)
Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>
2026-07-04 00:52:10 -05:00
Chris TitusandGitHub 640b02868a fix(iso): resolve windows update re-enabling failures on first boot (#4807)
* fix iso update service reenable

* test allow font scale sync state
2026-07-04 00:50:45 -05:00
29b269201d Add font scaling keyboard and mouse shortcuts (#4781)
* Add font scaling shortcuts

* Fix font scaling shortcut modifiers

---------

Co-authored-by: Chris Titus <contact@christitus.com>
2026-07-04 00:32:39 -05:00
77 changed files with 519 additions and 224 deletions
+1
View File
@@ -71,6 +71,7 @@ jobs:
labels: |
automated
documentation
skip-changelog
- name: Check outputs
run: |
@@ -1,77 +0,0 @@
name: Issue slash commands
on:
issue_comment:
types: [created, edited]
jobs:
issueCommands:
# Skip this job if the comment was created/edited on a PR
if: ${{ !github.event.issue.pull_request }}
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: none
contents: read
steps:
- name: Process slash command
uses: actions/github-script@v9
with:
script: |
const allowedUsers = ["ChrisTitusTech", "og-mrk", "Marterich", "MyDrift-user", "Real-MullaC", "CodingWonders", "GabiNun2", "FluffyPunk"];
const commenter = context.payload.comment.user.login;
// Authorization check first — before any parsing of comment content
if (!allowedUsers.includes(commenter)) {
console.log(`User ${commenter} is not in the allowlist. Skipping.`);
return;
}
// Read comment body as data, never interpolated into shell
const body = context.payload.comment.body;
const issueNumber = context.issue.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
// /label 'name' or /label name
const labelMatch = body.match(/\/label\s+'([^']+)'|\/label\s+(\S+?)(?:\s|$)/);
if (labelMatch) {
const labelName = (labelMatch[1] || labelMatch[2]).trim();
console.log(`Adding label: ${labelName}`);
await github.rest.issues.addLabels({
owner, repo, issue_number: issueNumber,
labels: [labelName],
});
}
// /unlabel 'name' or /unlabel name
const unlabelMatch = body.match(/\/unlabel\s+'([^']+)'|\/unlabel\s+(\S+?)(?:\s|$)/);
if (unlabelMatch) {
const labelName = (unlabelMatch[1] || unlabelMatch[2]).trim();
console.log(`Removing label: ${labelName}`);
await github.rest.issues.removeLabel({
owner, repo, issue_number: issueNumber,
name: labelName,
});
}
// /close (optionally with 'not planned')
if (body.includes('/close')) {
const stateReason = body.includes('not planned') ? 'not_planned' : 'completed';
console.log(`Closing issue (reason: ${stateReason})`);
await github.rest.issues.update({
owner, repo, issue_number: issueNumber,
state: 'closed',
state_reason: stateReason,
});
}
// /open or /reopen
if (body.includes('/open') || body.includes('/reopen')) {
console.log('Reopening issue');
await github.rest.issues.update({
owner, repo, issue_number: issueNumber,
state: 'open',
});
}
+3 -1
View File
@@ -32,7 +32,9 @@ jobs:
body: 'Automated update of sponsors section'
branch: sponsors-update
delete-branch: true
labels: automated
labels: |
automated
skip-changelog
- name: Check outputs
run: |
+1 -1
View File
@@ -77,7 +77,7 @@ See https://github.com/ChrisTitusTech/winutil/blob/main/.github/CONTRIBUTING.md
These are the sponsors that help keep this project alive with monthly contributions.
<!-- sponsors --><a href="https://github.com/dwelfusius"><img src="https:&#x2F;&#x2F;github.com&#x2F;dwelfusius.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/mews-se"><img src="https:&#x2F;&#x2F;github.com&#x2F;mews-se.png" width="60px" alt="User avatar: Martin Stockzell" /></a><a href="https://github.com/jdiegmueller"><img src="https:&#x2F;&#x2F;github.com&#x2F;jdiegmueller.png" width="60px" alt="User avatar: Jason A. Diegmueller" /></a><a href="https://github.com/robertsandrock"><img src="https:&#x2F;&#x2F;github.com&#x2F;robertsandrock.png" width="60px" alt="User avatar: RMS" /></a><a href="https://github.com/paulsheets"><img src="https:&#x2F;&#x2F;github.com&#x2F;paulsheets.png" width="60px" alt="User avatar: Paul" /></a><a href="https://github.com/djones369"><img src="https:&#x2F;&#x2F;github.com&#x2F;djones369.png" width="60px" alt="User avatar: Dave J (WhamGeek)" /></a><a href="https://github.com/anthonymendez"><img src="https:&#x2F;&#x2F;github.com&#x2F;anthonymendez.png" width="60px" alt="User avatar: Anthony Mendez" /></a><a href="https://github.com/FatBastard0"><img src="https:&#x2F;&#x2F;github.com&#x2F;FatBastard0.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DursleyGuy"><img src="https:&#x2F;&#x2F;github.com&#x2F;DursleyGuy.png" width="60px" alt="User avatar: DursleyGuy" /></a><a href="https://github.com/DwayneTheRockLobster1"><img src="https:&#x2F;&#x2F;github.com&#x2F;DwayneTheRockLobster1.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/KieraKujisawa"><img src="https:&#x2F;&#x2F;github.com&#x2F;KieraKujisawa.png" width="60px" alt="User avatar: Kiera Meredith" /></a><a href="https://github.com/andrewpayne68"><img src="https:&#x2F;&#x2F;github.com&#x2F;andrewpayne68.png" width="60px" alt="User avatar: Andrew P" /></a><!-- sponsors -->
<!-- sponsors --><a href="https://github.com/ysaito8015"><img src="https:&#x2F;&#x2F;github.com&#x2F;ysaito8015.png" width="60px" alt="User avatar: Yusuke Saito" /></a><a href="https://github.com/dwelfusius"><img src="https:&#x2F;&#x2F;github.com&#x2F;dwelfusius.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/mews-se"><img src="https:&#x2F;&#x2F;github.com&#x2F;mews-se.png" width="60px" alt="User avatar: Martin Stockzell" /></a><a href="https://github.com/jdiegmueller"><img src="https:&#x2F;&#x2F;github.com&#x2F;jdiegmueller.png" width="60px" alt="User avatar: Jason A. Diegmueller" /></a><a href="https://github.com/robertsandrock"><img src="https:&#x2F;&#x2F;github.com&#x2F;robertsandrock.png" width="60px" alt="User avatar: RMS" /></a><a href="https://github.com/paulsheets"><img src="https:&#x2F;&#x2F;github.com&#x2F;paulsheets.png" width="60px" alt="User avatar: Paul" /></a><a href="https://github.com/djones369"><img src="https:&#x2F;&#x2F;github.com&#x2F;djones369.png" width="60px" alt="User avatar: Dave J (WhamGeek)" /></a><a href="https://github.com/anthonymendez"><img src="https:&#x2F;&#x2F;github.com&#x2F;anthonymendez.png" width="60px" alt="User avatar: Anthony Mendez" /></a><a href="https://github.com/FatBastard0"><img src="https:&#x2F;&#x2F;github.com&#x2F;FatBastard0.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DursleyGuy"><img src="https:&#x2F;&#x2F;github.com&#x2F;DursleyGuy.png" width="60px" alt="User avatar: DursleyGuy" /></a><a href="https://github.com/DwayneTheRockLobster1"><img src="https:&#x2F;&#x2F;github.com&#x2F;DwayneTheRockLobster1.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/KieraKujisawa"><img src="https:&#x2F;&#x2F;github.com&#x2F;KieraKujisawa.png" width="60px" alt="User avatar: Kiera Meredith" /></a><a href="https://github.com/andrewpayne68"><img src="https:&#x2F;&#x2F;github.com&#x2F;andrewpayne68.png" width="60px" alt="User avatar: Andrew P" /></a><a href="https://github.com/johanwildeboer"><img src="https:&#x2F;&#x2F;github.com&#x2F;johanwildeboer.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/lukas346"><img src="https:&#x2F;&#x2F;github.com&#x2F;lukas346.png" width="60px" alt="User avatar: Wook" /></a><a href="https://github.com/tsv31"><img src="https:&#x2F;&#x2F;github.com&#x2F;tsv31.png" width="60px" alt="User avatar: Sorin" /></a><!-- sponsors -->
---
+12 -12
View File
@@ -530,6 +530,15 @@
"winget": "TechPowerUp.GPU-Z",
"foss": false
},
"gsudo": {
"category": "Pro Tools",
"choco": "gsudo",
"content": "gsudo",
"description": "gsudo is a sudo equivalent for Windows. It allows you to run commands with elevated administrative privileges directly within the current console window.",
"link": "https://github.com/gerardog/gsudo",
"winget": "gerardog.gsudo",
"foss": true
},
"helium": {
"category": "Browsers",
"choco": "helium",
@@ -719,15 +728,6 @@
"winget": "XBMCFoundation.Kodi",
"foss": true
},
"lightshot": {
"category": "Multimedia Tools",
"choco": "lightshot",
"content": "Lightshot",
"description": "The fastest way to take a customizable screenshot.",
"link": "https://app.prntscr.com/",
"winget": "Skillbrains.Lightshot",
"foss": false
},
"lazygit": {
"category": "Development",
"choco": "lazygit",
@@ -1207,7 +1207,7 @@
"processmonitor": {
"category": "Microsoft Tools",
"choco": "procexp",
"content": "SysInternals Process Monitor",
"content": "Process Monitor",
"description": "SysInternals Process Monitor is an advanced monitoring tool that shows real-time file system, registry, and process/thread activity.",
"link": "https://docs.microsoft.com/en-us/sysinternals/downloads/procmon",
"winget": "Microsoft.Sysinternals.ProcessMonitor",
@@ -1396,7 +1396,7 @@
"tcpview": {
"category": "Microsoft Tools",
"choco": "tcpview",
"content": "SysInternals TCPView",
"content": "TCPView",
"description": "SysInternals TCPView is a network monitoring tool that displays a detailed list of all TCP and UDP endpoints on your system.",
"link": "https://docs.microsoft.com/en-us/sysinternals/downloads/tcpview",
"winget": "Microsoft.Sysinternals.TCPView",
@@ -1513,7 +1513,7 @@
"ungoogled": {
"category": "Browsers",
"choco": "ungoogled-chromium",
"content": "Ungoogled",
"content": "Ungoogled Chromium",
"description": "Ungoogled Chromium is a version of Chromium without Google's integration for enhanced privacy and control.",
"link": "https://github.com/Eloston/ungoogled-chromium",
"winget": "eloston.ungoogled-chromium",
+52 -8
View File
@@ -179,6 +179,17 @@
"function": "Invoke-WPFFixesWinget",
"link": "https://winutil.christitus.com/dev/features/fixes/winget"
},
"WPFPanelComputer": {
"Content": "Computer Management",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"compmgmt.msc"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/computer"
},
"WPFPanelControl": {
"Content": "Control Panel",
"category": "Legacy Windows Panels",
@@ -190,16 +201,16 @@
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/control"
},
"WPFPanelComputer": {
"Content": "Computer Management",
"WPFPanelMouse": {
"Content": "Mouse Properties",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"compmgmt.msc"
"main.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/computer"
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/mouse"
},
"WPFPanelNetwork": {
"Content": "Network Connections",
@@ -234,6 +245,17 @@
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/printer"
},
"WPFPanelPrograms": {
"Content": "Programs and Features",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"appwiz.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/programs"
},
"WPFPanelRegion": {
"Content": "Region",
"category": "Legacy Windows Panels",
@@ -245,16 +267,16 @@
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/region"
},
"WPFPanelRestore": {
"Content": "Windows Restore",
"WPFPanelSecurity": {
"Content": "Security and Maintenance",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"rstrui.exe"
"wscui.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/restore"
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/security"
},
"WPFPanelSound": {
"Content": "Sound Settings",
@@ -289,6 +311,28 @@
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/timedate"
},
"WPFPanelFirewall": {
"Content": "Windows Defender Firewall",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"firewall.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/firewall"
},
"WPFPanelRestore": {
"Content": "Windows Restore",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"rstrui.exe"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/restore"
},
"WPFWinUtilInstallPSProfile": {
"Content": "CTT PowerShell Profile - Install",
"category": "Powershell Profile Powershell 7+ Only",
+5 -4
View File
@@ -1,9 +1,10 @@
{
"shared": {
"AppEntryWidth": "200",
"AppEntryFontSize": "11",
"AppEntryMargin": "1,0,1,0",
"AppEntryBorderThickness": "0",
"AppEntryWidth": "220",
"AppEntryFontSize": "13.2",
"AppEntryIconSize": "28",
"AppEntryMargin": "3",
"AppEntryBorderThickness": "1",
"CustomDialogFontSize": "12",
"CustomDialogFontSizeHeader": "14",
"CustomDialogLogoSize": "25",
+17 -1
View File
@@ -429,7 +429,7 @@
},
"WPFTweaksConsumerFeatures": {
"Content": "ConsumerFeatures - Disable",
"Description": "Windows will not automatically install any games, third-party apps, or application links from the Windows Store for the signed-in user. Some default Apps will be inaccessible (e.g. Phone Link).",
"Description": "Stops promoted app installs and reduces app suggestions from Microsoft Store content.",
"category": "Essential Tweaks",
"panel": "1",
"registry": [
@@ -944,6 +944,22 @@
],
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/wpbt"
},
"WPFTweaksPreventDeviceMetadataFromNetwork": {
"Content": "Prevent Device Companion Apps",
"Description": "Prevents additional software from being installed when plugging in devices (e.g. Ads when plugging in a monitor). Poses potential security risk.",
"category": "Essential Tweaks",
"panel": "1",
"registry": [
{
"Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Device Metadata",
"Name": "PreventDeviceMetadataFromNetwork",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
}
],
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/preventdevicemetadatafromnetwork"
},
"WPFTweaksRazerBlock": {
"Content": "Razer Software Auto-Install - Disable",
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software.",
+1 -1
View File
@@ -5,7 +5,7 @@ toc: false
---
> [!NOTE]
> This section contains technical documentation for developers. For end-user documentation, see the [User Guide](../userguide/).
> This section contains code-only references. For end-user documentation, see the [User Guide](../userguide/).
## Architecture
@@ -3,7 +3,7 @@ title: "Computer Management"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=193}
```json {filename="config/feature.json",linenos=inline,linenostart=182}
"WPFPanelComputer": {
"Content": "Computer Management",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "Control Panel"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=182}
```json {filename="config/feature.json",linenos=inline,linenostart=193}
"WPFPanelControl": {
"Content": "Control Panel",
"category": "Legacy Windows Panels",
@@ -0,0 +1,16 @@
---
title: "Windows Defender Firewall"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=314}
"WPFPanelFirewall": {
"Content": "Windows Defender Firewall",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"firewall.cpl"
],
```
@@ -0,0 +1,16 @@
---
title: "Mouse Properties"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=204}
"WPFPanelMouse": {
"Content": "Mouse Properties",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"main.cpl"
],
```
@@ -3,7 +3,7 @@ title: "Network Connections"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=204}
```json {filename="config/feature.json",linenos=inline,linenostart=215}
"WPFPanelNetwork": {
"Content": "Network Connections",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "Power Panel"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=215}
```json {filename="config/feature.json",linenos=inline,linenostart=226}
"WPFPanelPower": {
"Content": "Power Panel",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "Printer Panel"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=226}
```json {filename="config/feature.json",linenos=inline,linenostart=237}
"WPFPanelPrinter": {
"Content": "Printer Panel",
"category": "Legacy Windows Panels",
@@ -0,0 +1,16 @@
---
title: "Programs and Features"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=248}
"WPFPanelPrograms": {
"Content": "Programs and Features",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"appwiz.cpl"
],
```
@@ -3,7 +3,7 @@ title: "Region"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=237}
```json {filename="config/feature.json",linenos=inline,linenostart=259}
"WPFPanelRegion": {
"Content": "Region",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "Windows Restore"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=248}
```json {filename="config/feature.json",linenos=inline,linenostart=325}
"WPFPanelRestore": {
"Content": "Windows Restore",
"category": "Legacy Windows Panels",
@@ -0,0 +1,16 @@
---
title: "Security and Maintenance"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=270}
"WPFPanelSecurity": {
"Content": "Security and Maintenance",
"category": "Legacy Windows Panels",
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"wscui.cpl"
],
```
@@ -3,7 +3,7 @@ title: "Sound Settings"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=259}
```json {filename="config/feature.json",linenos=inline,linenostart=281}
"WPFPanelSound": {
"Content": "Sound Settings",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "System Properties"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=270}
```json {filename="config/feature.json",linenos=inline,linenostart=292}
"WPFPanelSystem": {
"Content": "System Properties",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "Time and Date"
description: ""
---
```json {filename="config/feature.json",linenos=inline,linenostart=281}
```json {filename="config/feature.json",linenos=inline,linenostart=303}
"WPFPanelTimedate": {
"Content": "Time and Date",
"category": "Legacy Windows Panels",
@@ -3,7 +3,7 @@ title: "System Tray Battery Percentage"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1252}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1268}
"WPFToggleBatteryPercentage": {
"Content": "System Tray Battery Percentage",
"Description": "Shows numeric battery percentage next to the battery icon in the system tray.",
@@ -3,7 +3,7 @@ title: "Start Menu Bing Search"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1605}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1621}
"WPFToggleBingSearch": {
"Content": "Start Menu Bing Search",
"Description": "Toggles Bing web search results in Windows Search.",
@@ -3,7 +3,7 @@ title: "Dark Theme for Windows"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1270}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1286}
"WPFToggleDarkMode": {
"Content": "Dark Theme for Windows",
"Description": "Dark Mode for the system and applications.",
@@ -3,7 +3,7 @@ title: "BSoD Verbose Mode"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1226}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1242}
"WPFToggleDetailedBSoD": {
"Content": "BSoD Verbose Mode",
"Description": "Gives more information when you blue screen.",
@@ -3,7 +3,7 @@ title: "Lock Screen - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1641}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1657}
"WPFTweaksDisableLockscreen": {
"Content": "Lock Screen - Disable",
"Description": "Skips the lock screen entirely and goes directly to the sign-in screen on boot and wake.",
@@ -3,7 +3,7 @@ title: "Game Mode"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1784}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1800}
"WPFToggleGameMode": {
"Content": "Game Mode",
"Description": "Toggles Windows prioritizes gaming performance by allocating system resources to games.",
@@ -3,7 +3,7 @@ title: "File Explorer Hidden Files"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1340}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1356}
"WPFToggleHiddenFiles": {
"Content": "File Explorer Hidden Files",
"Description": "Reveals hidden files in Explorer.",
@@ -3,7 +3,7 @@ title: "Settings Home Page"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1587}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1603}
"WPFToggleHideSettingsHome": {
"Content": "Settings Home Page",
"Description": "Toggles the Home Page in the Windows Settings app.",
@@ -3,7 +3,7 @@ title: "Logon Screen Acrylic Blur"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1623}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1639}
"WPFToggleLoginBlur": {
"Content": "Logon Screen Acrylic Blur",
"Description": "Toggles the acrylic blur effect on login screen background.",
@@ -3,7 +3,7 @@ title: "Enable Long Paths"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1810}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1826}
"WPFToggleLongPaths": {
"Content": "Enable Long Paths",
"Description": "Toggles support for file paths longer than 260 characters in Explorer.",
@@ -3,7 +3,7 @@ title: "Mouse Acceleration"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1473}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1489}
"WPFToggleMouseAcceleration": {
"Content": "Mouse Acceleration",
"Description": "Makes it so Cursor movement is affected by the speed of your physical mouse movements.",
@@ -3,7 +3,7 @@ title: "Multiplane Overlay"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1447}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1463}
"WPFToggleMultiplaneOverlay": {
"Content": "Multiplane Overlay",
"Description": "Multiplane Overlay compose multiple image layers, which can sometimes cause issues with graphics cards.",
@@ -3,7 +3,7 @@ title: "Microsoft Outlook New Version"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1386}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1402}
"WPFToggleNewOutlook": {
"Content": "Microsoft Outlook New Version",
"Description": "This will ensures the classic Outlook application is used.",
@@ -3,7 +3,7 @@ title: "Num Lock on Startup"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1507}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1523}
"WPFToggleNumLock": {
"Content": "Num Lock on Startup",
"Description": "Toggle the Num Lock key state when your computer starts.",
@@ -3,7 +3,7 @@ title: "S3 Sleep"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1569}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1585}
"WPFToggleS3Sleep": {
"Content": "S3 Sleep",
"Description": "Toggles between Modern Standby and S3 Sleep, which cuts off power to the CPU while continuing to refresh the memory.",
@@ -3,7 +3,7 @@ title: "Scrollbars Always Visible"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1428}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1444}
"WPFToggleScrollbars": {
"Content": "Scrollbars Always Visible",
"Description": "If enabled, scrollbars will always be visible. If disabled, Windows will automatically hide scrollbars when not in use.",
@@ -3,7 +3,7 @@ title: "File Explorer File Extensions"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1312}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1328}
"WPFToggleShowExt": {
"Content": "File Explorer File Extensions",
"Description": "Shows .file extensions in Explorer (.exe, .png, etc.)",
@@ -3,7 +3,7 @@ title: "S0 Sleep Network Connectivity"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1551}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1567}
"WPFToggleStandbyFix": {
"Content": "S0 Sleep Network Connectivity",
"Description": "Toggles network connectivity during S0 Sleep which is low power idle in modern laptops.",
@@ -3,7 +3,7 @@ title: "Start Menu Recommendations"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1658}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1674}
"WPFToggleStartMenuRecommendations": {
"Content": "Start Menu Recommendations",
"Description": "Toggles the recommendations section in the Start Menu. WARNING: This will also disable Windows Spotlight on your Lock Screen as a side effect.",
@@ -3,7 +3,7 @@ title: "Sticky Keys"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1702}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1718}
"WPFToggleStickyKeys": {
"Content": "Sticky Keys",
"Description": "Toggles the Sticky Keys, which activate when clicking shift rapidly.",
@@ -3,7 +3,7 @@ title: "Taskbar Task View Icon"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1766}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1782}
"WPFToggleTaskView": {
"Content": "Taskbar Task View Icon",
"Description": "Toggles the Task View Button in the Taskbar.",
@@ -3,7 +3,7 @@ title: "Taskbar Centered Icons"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1720}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1736}
"WPFToggleTaskbarAlignment": {
"Content": "Taskbar Centered Icons",
"Description": "Toggles the Taskbar alignment either to the left or center.",
@@ -3,7 +3,7 @@ title: "Taskbar Search Icon"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1748}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1764}
"WPFToggleTaskbarSearch": {
"Content": "Taskbar Search Icon",
"Description": "Toggles the Search Button on the Taskbar.",
@@ -3,7 +3,7 @@ title: "Logon Verbose Mode"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1368}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1384}
"WPFToggleVerboseLogon": {
"Content": "Logon Verbose Mode",
"Description": "Show detailed messages during startup/shutdown.",
@@ -3,7 +3,7 @@ title: "Window Snapping"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1533}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1549}
"WPFToggleWindowSnapping": {
"Content": "Window Snapping",
"Description": "Toggles the window snapping feature when dragging windows.",
@@ -6,7 +6,7 @@ description: ""
```json {filename="config/tweaks.json",linenos=inline,linenostart=430}
"WPFTweaksConsumerFeatures": {
"Content": "ConsumerFeatures - Disable",
"Description": "Windows will not automatically install any games, third-party apps, or application links from the Windows Store for the signed-in user. Some default Apps will be inaccessible (e.g. Phone Link).",
"Description": "Stops promoted app installs and reduces app suggestions from Microsoft Store content.",
"category": "Essential Tweaks",
"panel": "1",
"registry": [
@@ -3,7 +3,7 @@ title: "Temporary Files - Remove"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1066}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1082}
"WPFTweaksDeleteTempFiles": {
"Content": "Temporary Files - Remove",
"Description": "Erases TEMP Folders.",
@@ -3,7 +3,7 @@ title: "File Explorer Automatic Folder Discovery - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1171}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1187}
"WPFTweaksDisableExplorerAutoDiscovery": {
"Content": "File Explorer Automatic Folder Discovery - Disable",
"Description": "Windows Explorer automatically tries to guess the type of the folder based on its contents, slowing down the browsing experience. WARNING! Will disable File Explorer grouping.",
@@ -3,7 +3,7 @@ title: "Disk Cleanup - Run"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1053}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1069}
"WPFTweaksDiskCleanup": {
"Content": "Disk Cleanup - Run",
"Description": "Runs Disk Cleanup on Drive C: and removes old Windows Updates.",
@@ -0,0 +1,27 @@
---
title: "Prevent Device Companion Apps"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=947}
"WPFTweaksPreventDeviceMetadataFromNetwork": {
"Content": "Prevent Device Companion Apps",
"Description": "Prevents additional software from being installed when plugging in devices (e.g. Ads when plugging in a monitor). Poses potential security risk.",
"category": "Essential Tweaks",
"panel": "1",
"registry": [
{
"Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Device Metadata",
"Name": "PreventDeviceMetadataFromNetwork",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
}
],
```
## Registry Changes
Applications and System Components store and retrieve configuration data to modify Windows settings, so we can use the registry to change many settings in one place.
You can find information about the registry on [Wikipedia](https://en.wikipedia.org/wiki/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).
@@ -3,7 +3,7 @@ title: "Adobe URL Block List - Enable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1011}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1027}
"WPFTweaksBlockAdobeNet": {
"Content": "Adobe URL Block List - Enable",
"Description": "Reduces user interruptions by selectively blocking connections to Adobe's activation and telemetry servers. Credit: Ruddernation-Designs",
@@ -3,7 +3,7 @@ title: "Background Apps - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1139}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1155}
"WPFTweaksDisableBGapps": {
"Content": "Background Apps - Disable",
"Description": "Disables all Microsoft Store apps from running in the background, which has to be done individually since Windows 11.",
@@ -3,7 +3,7 @@ title: "Fullscreen Optimizations - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1155}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1171}
"WPFTweaksDisableFSO": {
"Content": "Fullscreen Optimizations - Disable",
"Description": "Disables FSO in all applications. NOTE: This will disable Color Management in Exclusive Fullscreen.",
@@ -3,7 +3,7 @@ title: "IPv6 - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1117}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1133}
"WPFTweaksDisableIPv6": {
"Content": "IPv6 - Disable",
"Description": "Disables IPv6.",
@@ -3,7 +3,7 @@ title: "System Tray Notifications & Calendar - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=988}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1004}
"WPFTweaksDisableNotifications": {
"Content": "System Tray Notifications & Calendar - Disable",
"Description": "Disables all Notifications INCLUDING Calendar.",
@@ -3,7 +3,7 @@ title: "IPv6 - Set IPv4 as Preferred"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1079}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1095}
"WPFTweaksIPv46": {
"Content": "IPv6 - Set IPv4 as Preferred",
"Description": "Setting the IPv4 preference can have latency and security benefits on private networks where IPv6 is not configured.",
@@ -3,7 +3,7 @@ title: "Razer Software Auto-Install - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=947}
```json {filename="config/tweaks.json",linenos=inline,linenostart=963}
"WPFTweaksRazerBlock": {
"Content": "Razer Software Auto-Install - Disable",
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software.",
@@ -3,7 +3,7 @@ title: "Right-Click Menu Previous Layout - Enable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1037}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1053}
"WPFTweaksRightClickMenu": {
"Content": "Right-Click Menu Previous Layout - Enable",
"Description": "Restores the classic context menu when right-clicking in File Explorer, replacing the simplified Windows 11 version.",
@@ -3,7 +3,7 @@ title: "Teredo - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1095}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1111}
"WPFTweaksTeredo": {
"Content": "Teredo - Disable",
"Description": "Teredo network tunneling is an IPv6 feature that can cause additional latency, but may cause problems with some games.",
@@ -3,7 +3,7 @@ title: "DNS - Set to:"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1835}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1851}
"WPFchangedns": {
"Content": "DNS - Set to:",
"category": "z__Advanced Tweaks - CAUTION",
@@ -60,6 +60,30 @@ function Initialize-InstallAppEntry {
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
})
$contentPanel = New-Object Windows.Controls.StackPanel
$contentPanel.Orientation = "Horizontal"
$contentPanel.VerticalAlignment = [Windows.VerticalAlignment]::Center
$icon = New-Object Windows.Controls.Grid
$icon.SetResourceReference([Windows.FrameworkElement]::WidthProperty, "AppEntryIconSize")
$icon.SetResourceReference([Windows.FrameworkElement]::HeightProperty, "AppEntryIconSize")
$icon.Margin = New-Object Windows.Thickness(0, 0, 8, 0)
$fallback = New-Object Windows.Controls.TextBlock
$fallback.Text = $app.content.TrimStart(".").Substring(0, 1).ToUpper()
$fallback.FontWeight = "Bold"; $fallback.HorizontalAlignment = "Center"; $fallback.VerticalAlignment = "Center"
if ($app.link) { $fallback.Visibility = "Collapsed" }
$fallback.SetResourceReference([Windows.Controls.TextBlock]::FontSizeProperty, "AppEntryFontSize")
$fallback.SetResourceReference([Windows.Controls.TextBlock]::ForegroundProperty, "ToggleButtonOnColor")
[void]$icon.Children.Add($fallback)
if ($app.link) {
$logo = New-Object Windows.Controls.Image
$logo.Stretch = [Windows.Media.Stretch]::Uniform
$logo.Source = "https://www.google.com/s2/favicons?sz=64&domain_url=$([uri]::EscapeDataString($app.link))"
$logo.Add_ImageFailed({ $this.Visibility = "Collapsed"; $this.Parent.Children[0].Visibility = "Visible" })
[void]$icon.Children.Add($logo)
}
[void]$contentPanel.Children.Add($icon)
# Create the TextBlock for the application name
$appName = New-Object Windows.Controls.TextBlock
$appName.Style = $sync.Form.Resources.AppEntryNameStyle
@@ -73,7 +97,8 @@ function Initialize-InstallAppEntry {
[void]$appName.Inlines.Add($fossRun)
}
$checkBox.Content = $appName
[void]$contentPanel.Children.Add($appName)
$checkBox.Content = $contentPanel
# Add accessibility properties to make the elements screen reader friendly
$checkBox.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $app.content)
@@ -78,6 +78,7 @@ function Invoke-WinUtilTweaks {
$sync.configs.tweaks.$CheckBox.appx | ForEach-Object {
Remove-WinUtilAPPX -Name $psitem
}
Remove-WinUtilProvisionedAPPX -PackageList $sync.configs.tweaks.$CheckBox.appx
}
}
Write-WinUtilLog -Component "Tweaks" -Message "$action tweak completed: $CheckBox"
+15 -2
View File
@@ -17,7 +17,20 @@ function Remove-WinUtilAPPX {
Write-Host "Removing $Name"
Write-WinUtilLog -Component "AppX" -Message "Removing AppX package pattern: $Name"
Get-AppxPackage $Name -AllUsers | Remove-AppxPackage -AllUsers
Get-AppxProvisionedPackage -Online | Where-Object DisplayName -like $Name | Remove-AppxProvisionedPackage -Online
# We explicitly loop through packages instead of using the pipeline because PowerShell 7 pipeline binding
# for Remove-AppxPackage fails silently, and Get-AppxPackage -AllUsers returns duplicate objects for each user profile.
$pkgs = Get-AppxPackage "*$Name*" -AllUsers | Sort-Object -Property PackageFullName -Unique
if ($null -ne $pkgs) {
foreach ($pkg in $pkgs) {
try {
Remove-AppxPackage -Package $pkg.PackageFullName -AllUsers -ErrorAction Stop
}
catch {
Write-WinUtilLog -Level "ERROR" -Component "AppX" -Message "Failed to remove AppX package $($pkg.PackageFullName): $($_.Exception.Message)"
}
}
}
Write-WinUtilLog -Component "AppX" -Message "AppX removal completed for package pattern: $Name"
}
@@ -0,0 +1,61 @@
function Remove-WinUtilProvisionedAPPX {
<#
.SYNOPSIS
Removes all AppX provisioned packages that match the given names
.PARAMETER PackageList
An array of names of the APPX packages to remove
.EXAMPLE
Remove-WinUtilProvisionedAPPX -PackageList @("Microsoft.Microsoft3DViewer", "Microsoft.WindowsCalculator")
#>
param (
[string[]]$PackageList
)
if ($null -eq $PackageList -or $PackageList.Count -eq 0) {
return
}
Write-Host "`nRemoving provisioned packages..."
Write-WinUtilLog -Component "AppX" -Message "Removing AppX provisioned packages: $($PackageList -join ', ')"
# DISM cmdlets like Get-AppxProvisionedPackage often fail with "Class not registered" or hang in PowerShell 7.
# We shell out to Windows PowerShell 5.1 (powershell.exe) to reliably remove the provisioned packages.
$ps5Command = {
$pkgs = $args
$provisionedPackages = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue
$failures = [System.Collections.Generic.List[string]]::new()
foreach ($Package in $pkgs) {
$provs = $provisionedPackages |
Where-Object DisplayName -Like "*$Package*"
if ($null -ne $provs) {
foreach ($prov in $provs) {
try {
Remove-AppxProvisionedPackage -Online -PackageName $prov.PackageName -ErrorAction Stop | Out-Null
}
catch {
$failures.Add("Failed to remove provisioned AppX package $($prov.PackageName): $($_.Exception.Message)")
}
}
}
}
if ($failures.Count -gt 0) {
throw ($failures -join [Environment]::NewLine)
}
}
$removalOutput = powershell.exe -NoProfile -NonInteractive -Command $ps5Command -args $PackageList 2>&1
if ($LASTEXITCODE -ne 0 -or $null -ne $removalOutput) {
$failureDetails = ($removalOutput | Out-String).Trim()
Write-WinUtilLog -Level "ERROR" -Component "AppX" -Message "AppX provisioned package removal failed: $failureDetails"
return
}
Write-WinUtilLog -Component "AppX" -Message "AppX provisioned package removal completed."
}
+10 -4
View File
@@ -13,11 +13,13 @@ function Invoke-WPFAppxRemoval {
$sync.ProcessRunning = $true
Write-WinUtilLog -Component "AppX" -Message "Starting AppX removal for $(@($selected).Count) selected package(s)."
$packageList = [System.Collections.Generic.List[string]]::new()
foreach ($key in $selected) {
if ($key -eq "WPFAppxMicrosoft_XboxGamingOverlay") {
# Making sure Game Bar isn't running
Write-WinUtilLog -Component "AppX" -Message "Stopping GameBarFTServer before removing Xbox Gaming Overlay."
Stop-Process -Name GameBarFTServer
Stop-Process -Name GameBarFTServer -Force -Confirm:$false -ErrorAction SilentlyContinue
# This stops annoying ms-gamebar popup when launching games.
Write-WinUtilLog -Component "AppX" -Message "Disabling Game DVR capture before removing Xbox Gaming Overlay."
@@ -25,14 +27,14 @@ function Invoke-WPFAppxRemoval {
}
if ($key -eq "WPFAppxMicrosoft_WindowsNotepad") {
# i hope your having fun reading this
Write-WinUtilLog -Component "AppX" -Message "Stopping dllhost before removing Notepad."
Stop-Process -Name dllhost
Stop-Process -Name dllhost -Force -Confirm:$false -ErrorAction SilentlyContinue
}
Write-Host "Removing $($apps[$key].Content)"
Write-WinUtilLog -Component "AppX" -Message "Removing $($apps[$key].Content) ($($apps[$key].PackageId))."
Get-AppxPackage -Name $apps[$key].PackageId -AllUsers | Remove-AppxPackage -AllUsers
Remove-WinUtilAPPX -Name $apps[$key].PackageId
$packageList.Add($apps[$key].PackageId)
if ($key -eq "WPFAppxMSTeams") {
# Uninstalls Microsoft Teams Meeting Add-in for Microsoft Office
@@ -41,6 +43,10 @@ function Invoke-WPFAppxRemoval {
}
}
if ($packageList.Count -gt 0) {
Remove-WinUtilProvisionedAPPX -PackageList $packageList.ToArray()
}
Write-Host "================================="
Write-Host "-- AppX Removal Finished ---"
Write-Host "================================="
+2
View File
@@ -65,6 +65,8 @@ function Invoke-WPFButton {
"WPFUpdatessecurity" {Invoke-WPFUpdatessecurity}
"WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"}
"WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"}
"WPFAppxRemoval" {Invoke-WPFTab "WPFTab6BT"}
"WPFBackToTweaks" {Invoke-WPFTab "WPFTab2BT"}
"WPFRemoveSelectedAppx" {Invoke-WPFAppxRemoval}
"WPFDefaultAppxSelection" {Invoke-WPFPresets "AppxDefault" -checkboxfilterpattern "WPFAppx*"}
"WPFSelectAllAppx" {
+1 -2
View File
@@ -19,13 +19,12 @@ function Invoke-WPFTab {
$tabNumber = [int]($ClickedTab -replace "WPFTab","" -replace "BT","") - 1
$filter = Get-WinUtilVariables -Type ToggleButton | Where-Object {$psitem -like "WPFTab?BT"}
$sync.$tabNav.Items[$tabNumber].IsSelected = $true
($sync.GetEnumerator()).where{$psitem.Key -in $filter} | ForEach-Object {
if ($ClickedTab -ne $PSItem.name) {
$sync[$PSItem.Name].IsChecked = $false
} else {
$sync["$ClickedTab"].IsChecked = $true
$tabNumber = [int]($ClickedTab-replace "WPFTab","" -replace "BT","") - 1
$sync.$tabNav.Items[$tabNumber].IsSelected = $true
}
}
$sync.currentTab = $sync.$tabNav.Items[$tabNumber].Header
+1 -1
View File
@@ -441,7 +441,7 @@ function Invoke-WPFUIElements {
$sync[$entryInfo.Name].Add_Unchecked({
[System.Object]$Sender = $args[0]
Invoke-WPFSelectedCheckboxesUpdate -type "Remove" -checkbox $Sender.name
Invoke-WPFSelectedCheckboxesUpdate -type "Remove" -checkboxName $Sender.name
})
}
}
+113 -21
View File
@@ -5,8 +5,21 @@
BeforeAll {
$script:repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
. (Join-Path $script:repoRoot "functions\private\Remove-WinUtilAPPX.ps1")
. (Join-Path $script:repoRoot "functions\private\Remove-WinUtilProvisionedAPPX.ps1")
. (Join-Path $script:repoRoot "functions\public\Invoke-WPFAppxRemoval.ps1")
$tokens = $null
$parseErrors = $null
$provisionedSourcePath = Join-Path $script:repoRoot "functions\private\Remove-WinUtilProvisionedAPPX.ps1"
$provisionedSourceAst = [System.Management.Automation.Language.Parser]::ParseFile($provisionedSourcePath, [ref]$tokens, [ref]$parseErrors)
$ps5CommandAssignment = $provisionedSourceAst.Find({
param($node)
$node -is [System.Management.Automation.Language.AssignmentStatementAst] -and
$node.Left -is [System.Management.Automation.Language.VariableExpressionAst] -and
$node.Left.VariablePath.UserPath -eq "ps5Command"
}, $true)
$script:provisionedRemovalScriptBlock = $ps5CommandAssignment.Right.Expression.ScriptBlock.GetScriptBlock()
function Write-WinUtilLog {
param($Message, $Level, $Component)
}
@@ -23,18 +36,25 @@ BeforeAll {
param(
[Parameter(ValueFromPipeline = $true)]
$InputObject,
[switch]$AllUsers
$Package,
[switch]$AllUsers,
$ErrorAction
)
process { }
}
function Remove-WinUtilProvisionedAPPX {
param($PackageList)
}
function Get-AppxProvisionedPackage {
param([switch]$Online)
param([switch]$Online, $ErrorAction)
}
function Remove-AppxProvisionedPackage {
param(
[Parameter(ValueFromPipeline = $true)]
$InputObject,
[switch]$Online
[switch]$Online,
$PackageName,
$ErrorAction
)
process { }
}
@@ -58,35 +78,90 @@ Describe "Remove-WinUtilAPPX" {
Mock Write-Host { }
Mock Write-WinUtilLog { }
Mock Get-AppxPackage {
[pscustomobject]@{
Name = $Name
}
@(
[pscustomobject]@{
Name = $Name
PackageFullName = "$Name.FullName"
}
[pscustomobject]@{
Name = $Name
PackageFullName = "$Name.FullName"
}
)
}
Mock Remove-AppxPackage { }
}
It "removes matching installed AppX packages" {
Remove-WinUtilAPPX -Name "Microsoft.Xbox*"
Should -Invoke -CommandName Get-AppxPackage -Times 1 -Exactly -ParameterFilter {
$Name -eq "*Microsoft.Xbox**" -and $AllUsers -eq $true
}
Should -Invoke -CommandName Remove-AppxPackage -Times 1 -Exactly -ParameterFilter {
$Package -eq "*Microsoft.Xbox**.FullName" -and
$AllUsers -eq $true -and
$ErrorAction -eq "Stop"
}
}
It "logs installed AppX removal failures" {
Mock Remove-AppxPackage { throw "Removal failed" }
{ Remove-WinUtilAPPX -Name "Example.Package" } | Should -Not -Throw
Should -Invoke -CommandName Write-WinUtilLog -Times 1 -Exactly -ParameterFilter {
$Level -eq "ERROR" -and
$Component -eq "AppX" -and
$Message -eq "Failed to remove AppX package *Example.Package*.FullName: Removal failed"
}
}
}
Describe "Remove-WinUtilProvisionedAPPX" {
BeforeEach {
Mock Get-AppxProvisionedPackage {
@(
[pscustomobject]@{ DisplayName = "Microsoft.XboxGamingOverlay" }
[pscustomobject]@{ DisplayName = "Microsoft.WindowsCalculator" }
[pscustomobject]@{ DisplayName = "Example.One"; PackageName = "Example.One_1.0" }
[pscustomobject]@{ DisplayName = "Example.Two"; PackageName = "Example.Two_1.0" }
)
}
Mock Remove-AppxProvisionedPackage { }
}
It "removes matching installed and provisioned AppX packages" {
Remove-WinUtilAPPX -Name "Microsoft.Xbox*"
It "queries provisioned packages once for all selected package names" {
& $script:provisionedRemovalScriptBlock "Example.One" "Example.Two"
Should -Invoke -CommandName Get-AppxPackage -Times 1 -Exactly -ParameterFilter {
$Name -eq "Microsoft.Xbox*" -and $AllUsers -eq $true
}
Should -Invoke -CommandName Remove-AppxPackage -Times 1 -Exactly -ParameterFilter {
$InputObject.Name -eq "Microsoft.Xbox*" -and $AllUsers -eq $true
}
Should -Invoke -CommandName Get-AppxProvisionedPackage -Times 1 -Exactly -ParameterFilter {
$Online -eq $true
}
Should -Invoke -CommandName Remove-AppxProvisionedPackage -Times 1 -Exactly -ParameterFilter {
$InputObject.DisplayName -eq "Microsoft.XboxGamingOverlay" -and $Online -eq $true
$PackageName -eq "Example.One_1.0" -and $Online -eq $true
}
Should -Invoke -CommandName Remove-AppxProvisionedPackage -Times 1 -Exactly -ParameterFilter {
$PackageName -eq "Example.Two_1.0" -and $Online -eq $true
}
}
It "surfaces provisioned package removal failures from the child process" {
Mock Remove-AppxProvisionedPackage { throw "DISM failed" }
{ & $script:provisionedRemovalScriptBlock "Example.One" } |
Should -Throw "*Failed to remove provisioned AppX package Example.One_1.0: DISM failed*"
Should -Invoke -CommandName Remove-AppxProvisionedPackage -Times 1 -Exactly -ParameterFilter {
$PackageName -eq "Example.One_1.0" -and
$Online -eq $true -and
$ErrorAction -eq "Stop"
}
}
It "handles child process failures before logging completion" {
$source = Get-Content -Path $provisionedSourcePath -Raw
$source | Should -Match '\$removalOutput = powershell\.exe .* 2>&1'
$source | Should -Match 'if \(\$LASTEXITCODE -ne 0 -or \$null -ne \$removalOutput\)'
$source | Should -Match 'Write-WinUtilLog -Level "ERROR" -Component "AppX" -Message "AppX provisioned package removal failed:'
$source | Should -Match '(?s)AppX provisioned package removal failed:.*return.*AppX provisioned package removal completed\.'
}
}
@@ -190,9 +265,11 @@ Describe "Invoke-WPFAppxRemoval runspace body" {
Mock Get-AppxPackage {
[pscustomobject]@{
Name = $Name
PackageFullName = "$Name.FullName"
}
}
Mock Remove-AppxPackage { }
Mock Remove-WinUtilProvisionedAPPX { }
Mock Get-Package {
[pscustomobject]@{
Name = "Microsoft Teams Meeting Add-in"
@@ -216,10 +293,13 @@ Describe "Invoke-WPFAppxRemoval runspace body" {
& $script:capturedAppxScriptBlock -selected $selected -apps $script:apps
Should -Invoke -CommandName Get-AppxPackage -Times 1 -Exactly -ParameterFilter {
$Name -eq "Example.Package" -and $AllUsers -eq $true
$Name -eq "*Example.Package*" -and $AllUsers -eq $true
}
Should -Invoke -CommandName Remove-AppxPackage -Times 1 -Exactly -ParameterFilter {
$InputObject.Name -eq "Example.Package" -and $AllUsers -eq $true
$Package -eq "*Example.Package*.FullName"
}
Should -Invoke -CommandName Remove-WinUtilProvisionedAPPX -Times 1 -Exactly -ParameterFilter {
$PackageList.Count -eq 1 -and $PackageList[0] -eq "Example.Package"
}
$script:sync.ProcessRunning | Should -BeFalse
}
@@ -239,7 +319,10 @@ Describe "Invoke-WPFAppxRemoval runspace body" {
& $script:capturedAppxScriptBlock -selected $selected -apps $script:apps
Should -Invoke -CommandName Stop-Process -Times 1 -Exactly -ParameterFilter {
$Name -eq "GameBarFTServer"
$Name -eq "GameBarFTServer" -and
$Force -eq $true -and
$Confirm -eq $false -and
$ErrorAction -eq "SilentlyContinue"
}
Should -Invoke -CommandName Set-ItemProperty -Times 1 -Exactly -ParameterFilter {
$Path -eq "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR" -and
@@ -247,7 +330,10 @@ Describe "Invoke-WPFAppxRemoval runspace body" {
$Value -eq 0
}
Should -Invoke -CommandName Stop-Process -Times 1 -Exactly -ParameterFilter {
$Name -eq "dllhost"
$Name -eq "dllhost" -and
$Force -eq $true -and
$Confirm -eq $false -and
$ErrorAction -eq "SilentlyContinue"
}
Should -Invoke -CommandName Get-Package -Times 1 -Exactly -ParameterFilter {
$Name -eq "Microsoft Teams*"
@@ -256,6 +342,12 @@ Describe "Invoke-WPFAppxRemoval runspace body" {
$InputObject.Name -eq "Microsoft Teams Meeting Add-in" -and $Force -eq $true
}
Should -Invoke -CommandName Remove-AppxPackage -Times 3 -Exactly
Should -Invoke -CommandName Remove-WinUtilProvisionedAPPX -Times 1 -Exactly -ParameterFilter {
$PackageList.Count -eq 3 -and
$PackageList[0] -eq "Microsoft.XboxGamingOverlay" -and
$PackageList[1] -eq "Microsoft.WindowsNotepad" -and
$PackageList[2] -eq "MSTeams"
}
$script:sync.ProcessRunning | Should -BeFalse
}
}
+8
View File
@@ -19,6 +19,9 @@ BeforeAll {
function Remove-WinUtilAPPX {
param($Name)
}
function Remove-WinUtilProvisionedAPPX {
param($PackageList)
}
function Set-WinUtilDNS {
param($DNSProvider)
}
@@ -89,6 +92,7 @@ Describe "Invoke-WinUtilTweaks" {
Mock Set-WinUtilRegistry { }
Mock Invoke-WinUtilScript { }
Mock Remove-WinUtilAPPX { }
Mock Remove-WinUtilProvisionedAPPX { }
Mock Write-WinUtilLog { }
Mock Write-Warning { }
}
@@ -118,6 +122,9 @@ Describe "Invoke-WinUtilTweaks" {
Should -Invoke -CommandName Remove-WinUtilAPPX -Times 1 -Exactly -ParameterFilter {
$Name -eq "Microsoft.ExampleApp"
}
Should -Invoke -CommandName Remove-WinUtilProvisionedAPPX -Times 1 -Exactly -ParameterFilter {
$PackageList.Count -eq 1 -and $PackageList[0] -eq "Microsoft.ExampleApp"
}
}
It "uses original registry values and service startup types in undo mode" {
@@ -137,6 +144,7 @@ Describe "Invoke-WinUtilTweaks" {
$Name -eq "WPFTweaksExample" -and $ScriptBlock.ToString() -eq "Write-Output 'undo tweak'"
}
Should -Invoke -CommandName Remove-WinUtilAPPX -Times 0 -Exactly
Should -Invoke -CommandName Remove-WinUtilProvisionedAPPX -Times 0 -Exactly
}
It "keeps a user-changed service startup type by default" {
+24 -1
View File
@@ -134,7 +134,6 @@ Describe "XAML document" {
"WPFTab3BT",
"WPFTab4BT",
"WPFTab5BT",
"WPFTab6BT",
"SearchBar",
"SearchBarClearButton",
"appscategory",
@@ -148,6 +147,7 @@ Describe "XAML document" {
"WPFAdvanced",
"WPFClearTweaksSelection",
"WPFGetInstalledTweaks",
"WPFAppxRemoval",
"WPFTweaksbutton",
"WPFUndoall",
"WPFUpdatesdefault",
@@ -157,6 +157,7 @@ Describe "XAML document" {
"WPFGetInstalledAppx",
"WPFSelectAllAppx",
"WPFClearAppxSelection",
"WPFBackToTweaks",
"WPFRemoveSelectedAppx"
)
@@ -223,6 +224,27 @@ Describe "XAML document" {
}
}
}
It "opens AppX removal from Tweaks and provides a return path" {
$navPanel = $script:xaml.SelectSingleNode('//*[local-name()="StackPanel"][@Name="NavDockPanel"]')
$tweaksTab = $script:xaml.SelectSingleNode('//*[local-name()="TabItem"][@Name="WPFTab2"]')
$appxTab = $script:xaml.SelectSingleNode('//*[local-name()="TabItem"][@Name="WPFTab6"]')
$openButton = $tweaksTab.SelectSingleNode('.//*[local-name()="Button"][@Name="WPFAppxRemoval"]')
$buttonNames = @($openButton.ParentNode.SelectNodes('./*[local-name()="Button"]') | ForEach-Object { $_.GetAttribute("Name") })
$getInstalledIndex = [array]::IndexOf($buttonNames, "WPFGetInstalledTweaks")
$openAppxIndex = [array]::IndexOf($buttonNames, "WPFAppxRemoval")
$buttonSource = Get-Content -Path $script:buttonScriptPath -Raw
$tabSource = Get-Content -Path (Join-Path $script:functionRoot "public\Invoke-WPFTab.ps1") -Raw
$navPanel.SelectSingleNode('./*[local-name()="ToggleButton"][@Name="WPFTab6BT"]') | Should -BeNullOrEmpty
$openButton.GetAttribute("Content").Trim() | Should -Be "AppX Removal"
$openAppxIndex | Should -Be ($getInstalledIndex + 1)
$appxTab.SelectSingleNode('.//*[local-name()="Button"][@Name="WPFBackToTweaks"]') | Should -Not -BeNullOrEmpty
$appxTab.SelectSingleNode('.//*[local-name()="Button"][@Name="WPFRemoveSelectedAppx"]') | Should -Not -BeNullOrEmpty
$buttonSource | Should -Match '"WPFAppxRemoval"\s*\{Invoke-WPFTab "WPFTab6BT"\}'
$buttonSource | Should -Match '"WPFBackToTweaks"\s*\{Invoke-WPFTab "WPFTab2BT"\}'
$tabSource | Should -Match '\$sync\.\$tabNav\.Items\[\$tabNumber\]\.IsSelected = \$true'
}
}
Describe "XAML and sync wiring" {
@@ -310,6 +332,7 @@ Describe "XAML and sync wiring" {
"InstallAppEntriesRendered",
"ProgressBar",
"progressBarTextBlock",
"FontScaleFactor",
"Win11ISOImageInfo",
"Win11ISODriveLetter",
"Win11ISOWimPath",
+14
View File
@@ -210,6 +210,8 @@ $sync.SearchBarClearButton.Add_Click({
})
# add some shortcuts for people that don't like clicking
function Invoke-WinUtilFontScaleStep([double]$Step) { $sync.FontScalingSlider.Value = [math]::Max(0.75, [math]::Min(2.0, $sync.FontScalingSlider.Value + $Step)); Invoke-WinUtilFontScaling -ScaleFactor $sync.FontScalingSlider.Value }
$commonKeyEvents = {
# Prevent shortcuts from executing if a process is already running
if ($sync.ProcessRunning -eq $true) {
@@ -233,13 +235,25 @@ $commonKeyEvents = {
}
# Handle Ctrl key combinations for specific actions
if ($_.KeyboardDevice.Modifiers -eq "Ctrl") {
$keyEventArgs = $_
switch ($_.Key) {
"F" { $sync.SearchBar.Focus() } # Focus on the search bar
"Q" { $this.Close() } # Close the application
}
}
$ctrlShiftModifiers = [Windows.Input.ModifierKeys]::Control -bor [Windows.Input.ModifierKeys]::Shift
if ($_.KeyboardDevice.Modifiers -eq "Ctrl" -or $_.KeyboardDevice.Modifiers -eq $ctrlShiftModifiers) {
$keyEventArgs = $_
switch ($_.Key) {
{ $_ -in "OemPlus", "Add" } { Invoke-WinUtilFontScaleStep 0.05; $keyEventArgs.Handled = $true }
{ $_ -in "OemMinus", "Subtract" } { Invoke-WinUtilFontScaleStep -0.05; $keyEventArgs.Handled = $true }
}
}
}
$sync["Form"].Add_PreViewKeyDown($commonKeyEvents)
$sync["Form"].Add_PreviewMouseWheel({
if ([Windows.Input.Keyboard]::Modifiers -eq "Ctrl") { Invoke-WinUtilFontScaleStep $(if ($_.Delta -gt 0) { 0.05 } else { -0.05 }); $_.Handled = $true }
})
$sync["Form"].Add_MouseLeftButtonDown({
Invoke-WPFPopup -Action "Hide" -Popups @("Settings", "Theme", "FontScaling")
+4 -4
View File
@@ -433,10 +433,10 @@ $scripts = @(
reg.exe delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" /v DODownloadMode /f;
reg.exe add "HKLM\Software\Policies\Microsoft\Windows\OneDrive" /v DisableFileSyncNGSC /t REG_DWORD /d 0 /f;
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\GameDVR" /v AppCaptureEnabled /t REG_DWORD /d 0 /f;
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\BITS" /v Start /t REG_DWORD /d 3 /f;
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\wuauserv" /v Start /t REG_DWORD /d 3 /f;
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\UsoSvc" /v Start /t REG_DWORD /d 2 /f;
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc" /v Start /t REG_DWORD /d 3 /f;
$services = @{ BITS = 'Manual'; wuauserv = 'Manual'; UsoSvc = 'Automatic'; WaaSMedicSvc = 'Manual' };
foreach ($name in $services.Keys) {
Set-Service -Name $name -StartupType $services[$name] -ErrorAction SilentlyContinue;
}
};
{
reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Education" /f;
+7 -34
View File
@@ -84,8 +84,8 @@
<Style x:Key="AppEntryBorderStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="BorderThickness" Value="{DynamicResource AppEntryBorderThickness}"/>
<Setter Property="CornerRadius" Value="2"/>
<Setter Property="Padding" Value="{DynamicResource AppEntryMargin}"/>
<Setter Property="CornerRadius" Value="5"/>
<Setter Property="Padding" Value="6,4"/>
<Setter Property="Width" Value="{DynamicResource AppEntryWidth}"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Margin" Value="{DynamicResource AppEntryMargin}"/>
@@ -100,30 +100,9 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<StackPanel Orientation="Horizontal">
<Grid Width="16" Height="16" Margin="0,0,8,0">
<Border Name="CheckBoxBorder"
BorderBrush="{DynamicResource MainForegroundColor}"
Background="{DynamicResource ButtonBackgroundColor}"
BorderThickness="1"
Width="12"
Height="12"
CornerRadius="2"/>
<Path Name="CheckMark"
Stroke="{DynamicResource ToggleButtonOnColor}"
StrokeThickness="2"
Data="M 2 8 L 6 12 L 14 4"
Visibility="Collapsed"/>
</Grid>
<ContentPresenter Content="{TemplateBinding Content}"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="CheckMark" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
<ContentPresenter Content="{TemplateBinding Content}"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</ControlTemplate>
</Setter.Value>
</Setter>
@@ -1004,14 +983,6 @@
</TextBlock>
</ToggleButton.Content>
</ToggleButton>
<ToggleButton Margin="0,0,5,0" Height="{DynamicResource TabButtonHeight}" Width="Auto" MinWidth="{DynamicResource TabButtonWidth}"
Background="{DynamicResource ButtonAppxBackgroundColor}" Foreground="{DynamicResource ButtonAppxForegroundColor}" FontWeight="Bold" Name="WPFTab6BT">
<ToggleButton.Content>
<TextBlock FontSize="{DynamicResource TabButtonFontSize}" Background="Transparent" Foreground="{DynamicResource ButtonAppxForegroundColor}">
<Underline>A</Underline>ppX Removal
</TextBlock>
</ToggleButton.Content>
</ToggleButton>
</StackPanel>
<!-- Search Bar and Action Buttons -->
@@ -1258,6 +1229,7 @@
<Button Name="WPFAdvanced" Content=" Advanced " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
<Button Name="WPFClearTweaksSelection" Content=" Clear " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
<Button Name="WPFGetInstalledTweaks" Content=" Get Installed Tweaks " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
<Button Name="WPFAppxRemoval" Content=" AppX Removal " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
</StackPanel>
</StackPanel>
@@ -1738,6 +1710,7 @@
<Border Grid.Row="1" Background="{DynamicResource MainBackgroundColor}" BorderBrush="{DynamicResource BorderColor}" BorderThickness="1" CornerRadius="5" HorizontalAlignment="Stretch" Padding="10">
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
<Button Name="WPFBackToTweaks" Content="Back to Tweaks" Margin="5" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
<Button Name="WPFRemoveSelectedAppx" Content="Remove Selected" Margin="5" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
</WrapPanel>
</Border>