Compare commits

..

23 Commits

Author SHA1 Message Date
Chris Titus Tech
d5d0bf25f0 automerge docs 2026-02-23 14:53:46 -06:00
Chris Titus Tech
da3fd87f9a revise approval 2026-02-23 14:46:15 -06:00
Chris Titus Tech
9e8cefc973 fix automerge 2026-02-23 14:43:52 -06:00
Gabi
a532e9ec9d Remove WPFTweaksDisableExplorerAutoDiscovery From Minimal Preset (#4081)
* WPFTweaksDisableExplorerAutoDiscovery Shouldn't not be deafult

* Update preset.json

* Update tweaks.json

* Update config/tweaks.json

Co-authored-by: Paweł Gwozdowski <kernea.g@proton.me>

---------

Co-authored-by: Paweł Gwozdowski <kernea.g@proton.me>
2026-02-23 10:17:01 -06:00
dependabot[bot]
844979fee7 Bump peter-evans/create-pull-request from 6 to 8 (#4104)
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6 to 8.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v6...v8)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 09:23:33 -06:00
Sean (ANGRYxScotsman)
78302934ef updated workflows for automation (#4102)
* updated workflows for automation

* added back the debug logs

* Update docs.yaml

* Update pre-release.yaml
2026-02-22 21:25:59 -06:00
Gabi
349889b194 Minor format changes for Invoke-WPFSystemRepair.ps1 (#4100)
* Format changes

* Update Invoke-WPFSystemRepair.ps1
2026-02-22 17:31:54 -06:00
Raphaël
c619f3a830 Add more development tools to applications.json (#4093)
* Add .NET Desktop Runtime 10 to applications.json

* Add LLVM to applications.json

* Add NASM to applications.json
2026-02-22 17:30:43 -06:00
KamaleiZestri
d005a225a2 NoUI mode and Concurrency edits (#4092)
* Autorun changes

* Missed a handle

* Remove todo

---------

Co-authored-by: Chris Titus <dfm.titus@gmail.com>
2026-02-22 17:28:55 -06:00
Gabi
e79e946e76 Remove incorrect infromaiton from WPFTweaksRazerBlock (#4082) 2026-02-22 17:23:19 -06:00
github-actions[bot]
3b957e1a77 Update sponsors in README (#4095)
Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>
2026-02-22 17:21:52 -06:00
Gabi
d078d67b1d Remove debug option (#4094)
* Remove debug option

* Remove debug option
2026-02-22 17:21:32 -06:00
Gabi
191fe95572 Update-KnownIssues.md (#4096)
* Update KnownIssues.md

* Update KnownIssues.md
2026-02-22 17:20:39 -06:00
Sean (ANGRYxScotsman)
d10c9413ac Update devdocs-generator (#4091)
* Update devdocs-generator.ps1

* made new dir

* Update devdocs-generator.ps1

* Update devdocs-generator.ps1
2026-02-22 17:19:43 -06:00
Chris Titus
e93753e5c9 Json-Cleanup-Expansion (#4090)
* initial cleanup

* remove winutilgpu
2026-02-22 17:19:04 -06:00
Gabi
5eec99df1c Fix title screen image url (#4087) 2026-02-18 15:29:41 -06:00
Gabi
7e2ba41b8b Update inputXML.xaml (#4089) 2026-02-18 15:29:14 -06:00
Chris Titus
d3dc3e7976 Merge branches 'main' and 'main' of https://github.com/ChrisTitusTech/winutil 2026-02-18 14:44:33 -06:00
Gabi
5a4d822710 Fix more images in CONTRIBUTING.md (#4086) 2026-02-18 14:44:19 -06:00
Chris Titus
2625478ef3 assign docs label 2026-02-18 14:41:00 -06:00
github-actions[bot]
956a544c2e Update generated documentation (#4084)
Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>
2026-02-18 14:33:39 -06:00
Gabi
50dbf5bd05 Fix fork image (#4085) 2026-02-18 14:32:29 -06:00
Gabi
338c3e7e57 Add warning to WPFToggleStartMenuRecommendations (#4083) 2026-02-18 14:31:38 -06:00
81 changed files with 572 additions and 464 deletions

View File

@@ -68,9 +68,9 @@ graph TD
### Fork the Repo
* Fork the WinUtil Repository [here](https://github.com/ChrisTitusTech/winutil) to create a copy that will be available in your repository list.
![Fork Image](assets/Fork-Button-Dark.png#only-dark#gh-dark-mode-only)
![Fork Image](/docs/assets/images/Fork-Button-Dark.png#gh-dark-mode-only)
![Fork Image](assets/Fork-Button-Light.png#only-light#gh-light-mode-only)
![Fork Image](/docs/assets/images/Fork-Button-Light.png#only-light#gh-light-mode-only)
### Clone the Fork
!!! tip
@@ -94,22 +94,22 @@ graph TD
* Run the following command to compile and run WinUtil:
* `.\Compile.ps1 -run`
![Compile](assets/Compile.png)
![Compile](/docs/assets/images/Complie.png)
* After seeing that your changes work properly, feel free to commit the changes to the repository and make a PR. For help on that, follow the documentation below.
### Committing the changes
* Before committing your changes, please discard changes made to the `winutil.ps1` file, like the following:
![Push Commit Image](assets/Discard-GHD.png)
![Push Commit Image](/docs/assets/images/Discard-GHD.png)
* Now, commit your changes once you are happy with the result.
![Commit Image](assets/Commit-GHD.png)
![Commit Image](/docs/assets/images/Commit-GHD.png)
* Push the changes to upload them to your fork on github.com.
![Push Commit Image](assets/Push-Commit.png)
![Push Commit Image](/docs/assets/images/Push-Commit.png)
### Making a PR
* To make a PR on your repo under a new branch linking to the main branch, a button will show and say Preview and Create pull request. Click that button and fill in all the information that is provided on the template. Once all the information is filled in correctly, check your PR to make sure there is not a WinUtil.ps1 file attached to the PR. Once everything is good, make the PR and wait for Chris (the maintainer) to accept or deny your PR. Once it is accepted by Chris, you will be able to see your changes in the "/windev" build.

View File

@@ -8,7 +8,7 @@ on:
jobs:
auto-merge:
if: github.event.pull_request.head.ref == 'docs-update' && github.event.pull_request.user.login == 'github-actions[bot]'
if: github.event.pull_request.head.ref == 'docs-update' && (github.event.pull_request.user.login == 'ChrisTitusTech' || github.event.pull_request.user.login == 'github-actions[bot]')
runs-on: ubuntu-latest
permissions:
pull-requests: write
@@ -18,13 +18,14 @@ jobs:
uses: actions/checkout@v6
- name: Auto-approve PR
if: github.event.pull_request.user.login == 'github-actions[bot]'
run: gh pr review "$PR_NUMBER" --approve
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.AUTO_MERGE }}
- name: Enable auto-merge
run: gh pr merge "$PR_NUMBER" --squash --auto --delete-branch
run: gh pr merge "$PR_NUMBER" --squash --delete-branch
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -12,7 +12,7 @@ on:
workflow_dispatch:
permissions:
contents: write
contents: read
pages: write
id-token: write
pull-requests: write
@@ -47,23 +47,30 @@ jobs:
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Generate Dev Docs from JSON
shell: pwsh
run: |
Set-Location tools
./devdocs-generator.ps1
- name: Create Pull Request 🚀
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'Update generated documentation'
token: ${{ secrets.AUTO_MERGE }}
commit-message: 'chore: Update generated dev docs'
title: 'chore: Update Generated Dev Docs'
body: 'Automated update of generated documentation from JSON sources'
branch: docs-update
delete-branch: true
labels: automated
add-paths: |
docs/content/dev/
config/tweaks.json
config/feature.json
labels: |
automated
documentation
- name: Check outputs
run: |

View File

@@ -3,6 +3,7 @@ name: Pre-Release WinUtil
permissions:
contents: write
actions: read
pull-requests: write
on:
workflow_dispatch: # Manual trigger added
@@ -22,25 +23,35 @@ jobs:
Set-Location tools
./devdocs-generator.ps1
- name: Commit Updated JSON Links
shell: pwsh
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add config/tweaks.json config/feature.json
$changes = git diff --cached --quiet; if ($LASTEXITCODE -ne 0) {
git commit -m "Update documentation links in JSON configs"
git push
} else {
Write-Host "No JSON link changes to commit"
}
- name: Compile project
shell: pwsh
run: |
Set-ExecutionPolicy Bypass -Scope Process -Force; ./Compile.ps1
continue-on-error: false # Directly fail the job on error, removing the need for a separate check
- name: Create Pull Request for Updated JSON Links
id: cpr
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.AUTO_MERGE }}
commit-message: 'chore: Update documentation links in JSON configs'
title: 'chore: Update Generated Dev Docs'
body: 'Automated update of documentation links in JSON configs from pre-release build'
branch: docs-update
delete-branch: true
add-paths: |
config/tweaks.json
config/feature.json
labels: |
automated
documentation
- name: Check outputs
shell: bash
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
- name: Set Version to Todays Date
id: extract_version
run: |

View File

@@ -24,7 +24,7 @@ jobs:
- name: Create Pull Request 🚀
id: cpr
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'Update sponsors in README'

View File

@@ -1,5 +1,4 @@
param (
[switch]$Debug,
[switch]$Run,
[string]$Arguments
)
@@ -106,17 +105,10 @@ $xaml
$script_content.Add($(Get-Content "scripts\main.ps1"))
if ($Debug) {
Update-Progress "Writing debug files" 95
$appXamlContent | Out-File -FilePath "xaml\inputApp.xaml" -Encoding ascii
$tweaksXamlContent | Out-File -FilePath "xaml\inputTweaks.xaml" -Encoding ascii
$featuresXamlContent | Out-File -FilePath "xaml\inputFeatures.xaml" -Encoding ascii
} else {
Update-Progress "Removing temporary files" 99
Remove-Item "xaml\inputApp.xaml" -ErrorAction SilentlyContinue
Remove-Item "xaml\inputTweaks.xaml" -ErrorAction SilentlyContinue
Remove-Item "xaml\inputFeatures.xaml" -ErrorAction SilentlyContinue
}
Update-Progress "Removing temporary files" 99
Remove-Item "xaml\inputApp.xaml" -ErrorAction SilentlyContinue
Remove-Item "xaml\inputTweaks.xaml" -ErrorAction SilentlyContinue
Remove-Item "xaml\inputFeatures.xaml" -ErrorAction SilentlyContinue
Set-Content -Path "$scriptname" -Value ($script_content -join "`r`n") -Encoding ascii
Write-Progress -Activity "Compiling" -Completed

View File

@@ -7,7 +7,7 @@
This utility is a compilation of Windows tasks I perform on each Windows system I use. It is meant to streamline *installs*, debloat with *tweaks*, troubleshoot with *config*, and fix Windows *updates*. I am extremely picky about any contributions to keep this project clean and efficient.
![screen-install](https://raw.githubusercontent.com/Chris-Titus-Docs/winutil-docs/refs/heads/main/assets/images/Title-Screen.png)
![screen-install](/docs/assets/images/Title-Screen.png)
## 💡 Usage
@@ -76,7 +76,7 @@ You'll see a new file named `winutil.ps1`, which's created by `Compile.ps1` scri
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/KenichiQaz"><img src="https:&#x2F;&#x2F;github.com&#x2F;KenichiQaz.png" width="60px" alt="User avatar: Stefan" /></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/quaszi"><img src="https:&#x2F;&#x2F;github.com&#x2F;quaszi.png" width="60px" alt="User avatar: " /></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/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/KenichiQaz"><img src="https:&#x2F;&#x2F;github.com&#x2F;KenichiQaz.png" width="60px" alt="User avatar: Stefan" /></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/quaszi"><img src="https:&#x2F;&#x2F;github.com&#x2F;quaszi.png" width="60px" alt="User avatar: " /></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/nathanzilgo"><img src="https:&#x2F;&#x2F;github.com&#x2F;nathanzilgo.png" width="60px" alt="User avatar: Nathan Fernandes Pedroza" /></a><!-- sponsors -->
## 🏅 Thanks to all Contributors
Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻.

View File

@@ -496,6 +496,14 @@
"link": "https://dotnet.microsoft.com/download/dotnet/9.0",
"winget": "Microsoft.DotNet.DesktopRuntime.9"
},
"dotnet10": {
"category": "Microsoft Tools",
"choco": "dotnet-10.0-runtime",
"content": ".NET Desktop Runtime 10",
"description": ".NET Desktop Runtime 10 is a runtime environment required for running applications developed with .NET 10.",
"link": "https://dotnet.microsoft.com/download/dotnet/10.0",
"winget": "Microsoft.DotNet.DesktopRuntime.10"
},
"dmt": {
"winget": "GNE.DualMonitorTools",
"choco": "dual-monitor-tools",
@@ -3226,5 +3234,23 @@
"link": "https://zed.dev/",
"winget": "ZedIndustries.Zed",
"foss": true
},
"LLLVM": {
"category": "Development",
"choco": "llvm",
"winget": "LLVM.LLVM",
"description": "A collection of modular and reusable compiler and toolchain technologies.",
"content": "LLVM",
"link": "https://llvm.org",
"foss": true
},
"NASM": {
"category": "Development",
"choco": "nasm",
"winget": "NASM.NASM",
"description": "A powerful assembler for the x86 platform.",
"content": "NASM",
"link": "https://nasm.us",
"foss": true
}
}

View File

@@ -4,7 +4,6 @@
"Description": ".NET and .NET Framework is a developer platform made up of tools, programming languages, and libraries for building many different types of applications.",
"category": "Features",
"panel": "1",
"Order": "a010_",
"feature": [
"NetFx4-AdvSrvs",
"NetFx3"
@@ -17,7 +16,6 @@
"Description": "Hyper-V is a hardware virtualization product developed by Microsoft that allows users to create and manage virtual machines.",
"category": "Features",
"panel": "1",
"Order": "a011_",
"feature": [
"Microsoft-Hyper-V-All"
],
@@ -31,7 +29,6 @@
"Description": "Enables legacy programs from previous versions of windows",
"category": "Features",
"panel": "1",
"Order": "a012_",
"feature": [
"WindowsMediaPlayer",
"MediaPlayback",
@@ -46,7 +43,6 @@
"Description": "Windows Subsystem for Linux is an optional feature of Windows that allows Linux programs to run natively on Windows without the need for a separate virtual machine or dual booting.",
"category": "Features",
"panel": "1",
"Order": "a020_",
"feature": [
"VirtualMachinePlatform",
"Microsoft-Windows-Subsystem-Linux"
@@ -59,7 +55,6 @@
"Description": "Network File System (NFS) is a mechanism for storing files on a network.",
"category": "Features",
"panel": "1",
"Order": "a014_",
"feature": [
"ServicesForNFS-ClientOnly",
"ClientForNFS-Infrastructure",
@@ -79,7 +74,6 @@
"Description": "Enables daily registry backup, previously disabled by Microsoft in Windows 10 1803.",
"category": "Features",
"panel": "1",
"Order": "a017_",
"feature": [],
"InvokeScript": [
"
@@ -97,7 +91,6 @@
"Description": "Enables Advanced Boot Options screen that lets you start Windows in advanced troubleshooting modes.",
"category": "Features",
"panel": "1",
"Order": "a018_",
"feature": [],
"InvokeScript": [
"bcdedit /set bootmenupolicy legacy"
@@ -109,7 +102,6 @@
"Description": "Disables Advanced Boot Options screen that lets you start Windows in advanced troubleshooting modes.",
"category": "Features",
"panel": "1",
"Order": "a019_",
"feature": [],
"InvokeScript": [
"bcdedit /set bootmenupolicy standard"
@@ -121,7 +113,6 @@
"Description": "Windows Sandbox is a lightweight virtual machine that provides a temporary desktop environment to safely run applications and programs in isolation.",
"category": "Features",
"panel": "1",
"Order": "a021_",
"feature": [
"Containers-DisposableClientVM"
],
@@ -131,54 +122,54 @@
"Content": "Install Features",
"category": "Features",
"panel": "1",
"Order": "a060_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFFeatureInstall",
"link": "https://winutil.christitus.com/dev/features/features/install"
},
"WPFPanelAutologin": {
"Content": "Set Up Autologin",
"category": "Fixes",
"Order": "a040_",
"panel": "1",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFPanelAutologin",
"link": "https://winutil.christitus.com/dev/features/fixes/autologin"
},
"WPFFixesUpdate": {
"Content": "Reset Windows Update",
"category": "Fixes",
"panel": "1",
"Order": "a041_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFFixesUpdate",
"link": "https://winutil.christitus.com/dev/features/fixes/update"
},
"WPFFixesNetwork": {
"Content": "Reset Network",
"category": "Fixes",
"Order": "a042_",
"panel": "1",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFFixesNetwork",
"link": "https://winutil.christitus.com/dev/features/fixes/network"
},
"WPFPanelDISM": {
"Content": "System Corruption Scan",
"category": "Fixes",
"panel": "1",
"Order": "a043_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFSystemRepair",
"link": "https://winutil.christitus.com/dev/features/fixes/dism"
},
"WPFFixesWinget": {
"Content": "WinGet Reinstall",
"category": "Fixes",
"panel": "1",
"Order": "a044_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFFixesWinget",
"link": "https://winutil.christitus.com/dev/features/fixes/winget"
},
"WPFPanelControl": {
@@ -187,6 +178,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"control"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/control"
},
"WPFPanelComputer": {
@@ -195,6 +189,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"compmgmt.msc"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/computer"
},
"WPFPanelNetwork": {
@@ -203,6 +200,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"ncpa.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/network"
},
"WPFPanelPower": {
@@ -211,6 +211,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"powercfg.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/power"
},
"WPFPanelPrinter": {
@@ -219,6 +222,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"Start-Process 'shell:::{A8A91A66-3A7D-4424-8D24-04E180695C7A}'"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/printer"
},
"WPFPanelRegion": {
@@ -227,6 +233,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"intl.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/region"
},
"WPFPanelRestore": {
@@ -235,6 +244,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"rstrui.exe"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/restore"
},
"WPFPanelSound": {
@@ -243,6 +255,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"mmsys.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/sound"
},
"WPFPanelSystem": {
@@ -251,6 +266,9 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"sysdm.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/system"
},
"WPFPanelTimedate": {
@@ -259,33 +277,36 @@
"panel": "2",
"Type": "Button",
"ButtonWidth": "300",
"InvokeScript": [
"timedate.cpl"
],
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/timedate"
},
"WPFWinUtilInstallPSProfile": {
"Content": "Install CTT PowerShell Profile",
"category": "Powershell Profile Powershell 7+ Only",
"panel": "2",
"Order": "a083_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WinUtilInstallPSProfile",
"link": "https://winutil.christitus.com/dev/features/powershell-profile-powershell-7--only/installpsprofile"
},
"WPFWinUtilUninstallPSProfile": {
"Content": "Uninstall CTT PowerShell Profile",
"category": "Powershell Profile Powershell 7+ Only",
"panel": "2",
"Order": "a084_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WinUtilUninstallPSProfile",
"link": "https://winutil.christitus.com/dev/features/powershell-profile-powershell-7--only/uninstallpsprofile"
},
"WPFWinUtilSSHServer": {
"Content": "Enable OpenSSH Server",
"category": "Remote Access",
"panel": "2",
"Order": "a084_",
"Type": "Button",
"ButtonWidth": "300",
"function": "Invoke-WPFSSHServer",
"link": "https://winutil.christitus.com/dev/features/remote-access/sshserver"
}
}

View File

@@ -16,7 +16,6 @@
],
"Minimal": [
"WPFTweaksConsumerFeatures",
"WPFTweaksDisableExplorerAutoDiscovery",
"WPFTweaksWPBT",
"WPFTweaksServices",
"WPFTweaksTelemetry"

View File

@@ -1907,7 +1907,7 @@
},
"WPFTweaksRazerBlock": {
"Content": "Block Razer Software Installs",
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software. WARNING: this will also block all Windows third-party driver installations.",
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software.",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"registry": [
@@ -2246,7 +2246,7 @@
},
"WPFToggleStartMenuRecommendations": {
"Content": "Recommendations in Start Menu",
"Description": "If disabled then you will not see recommendations in the Start Menu.",
"Description": "If disabled then you will not see recommendations in the Start Menu. WARNING: This will also disable Windows Spotlight on your Lock Screen as a side effect.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",
@@ -2615,7 +2615,7 @@
},
"WPFTweaksDisableExplorerAutoDiscovery": {
"Content": "Disable Explorer Automatic Folder Discovery",
"Description": "Windows Explorer automatically tries to guess the type of the folder based on its contents, slowing down the browsing experience.",
"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",
"category": "Essential Tweaks",
"panel": "1",
"InvokeScript": [

View File

@@ -27,6 +27,14 @@ If you are still having issues, try using a **VPN**, or changing your **DNS prov
| Cloudflare | `1.1.1.1` | `1.0.0.1` |
| Google | `8.8.8.8` | `8.8.4.4` |
### Script Won't Run
If your PowerShell session is running in **Constrained Language Mode**, some scripts and commands may fail to execute. To check the current language mode, run:
```powershell
$ExecutionContext.SessionState.LanguageMode
```
If it returns `ConstrainedLanguage`, you may need to switch to `FullLanguage` mode or run the script in a session with administrative privileges. Be aware that some security policies may enforce Constrained Language Mode, especially in corporate or managed environments.
### Script blocked by Execution Policy
1. Ensure you are running PowerShell as admin: Press `Windows Key`+`X` and select _PowerShell (Admin)_ in Windows 10, or `Windows Terminal (Admin)` in Windows 11.

View File

@@ -42,3 +42,11 @@ toc: false
### Features
{{< autolinks section="dev/features/features" >}}
### Remote Access
{{< autolinks section="dev/features/remote-access" >}}
### Powershell Profile Powershell 7+ Only
{{< autolinks section="dev/features/powershell-profile-powershell-7--only" >}}

View File

@@ -0,0 +1,7 @@
---
title: "Powershell Profile Powershell 7+ Only"
weight: 5
toc: false
---
{{< autolinks section="dev/features/powershell-profile-powershell-7--only" >}}

View File

@@ -0,0 +1,7 @@
---
title: "Remote Access"
weight: 4
toc: false
---
{{< autolinks section="dev/features/remote-access" >}}

View File

@@ -15,3 +15,11 @@ toc: false
### Features
{{< autolinks section="dev/features/features" >}}
### Remote Access
{{< autolinks section="dev/features/remote-access" >}}
### Powershell Profile Powershell 7+ Only
{{< autolinks section="dev/features/powershell-profile-powershell-7--only" >}}

View File

@@ -3,7 +3,7 @@ title: "Bing Search in Start Menu"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2186}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2185}
"WPFToggleBingSearch": {
"Content": "Bing Search in Start Menu",
"Description": "If enable then includes web search results from Bing in your Start Menu search.",

View File

@@ -3,7 +3,7 @@ title: "Dark Theme for Windows"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2144}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2143}
"WPFToggleDarkMode": {
"Content": "Dark Theme for Windows",
"Description": "Enable/Disable Dark Mode.",

View File

@@ -3,7 +3,7 @@ title: "Detailed BSoD"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2537}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2541}
"WPFToggleDetailedBSoD": {
"Content": "Detailed BSoD",
"Description": "If Enabled then you will see a detailed Blue Screen of Death (BSOD) with more information.",

View File

@@ -3,7 +3,7 @@ title: "Cross-Device Resume"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2667}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2671}
"WPFToggleDisableCrossDeviceResume": {
"Content": "Cross-Device Resume",
"Description": "This tweak controls the Resume function in Windows 11 24H2 and later, which allows you to resume an activity from a mobile device and vice-versa.",

View File

@@ -3,7 +3,7 @@ title: "Show Hidden Files"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2422}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2421}
"WPFToggleHiddenFiles": {
"Content": "Show Hidden Files",
"Description": "If Enabled then Hidden Files will be shown.",

View File

@@ -3,7 +3,7 @@ title: "Remove Settings Home Page"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2292}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2291}
"WPFToggleHideSettingsHome": {
"Content": "Remove Settings Home Page",
"Description": "Removes the Home page in the Windows Settings app.",

View File

@@ -3,7 +3,7 @@ title: "Mouse Acceleration"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2310}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2309}
"WPFToggleMouseAcceleration": {
"Content": "Mouse Acceleration",
"Description": "If Enabled then Cursor movement is affected by the speed of your physical mouse movements.",

View File

@@ -3,7 +3,7 @@ title: "Disable Multiplane Overlay"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2404}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2403}
"WPFToggleMultiplaneOverlay": {
"Content": "Disable Multiplane Overlay",
"Description": "Disable the Multiplane Overlay which can sometimes cause issues with Graphics Cards.",

View File

@@ -3,7 +3,7 @@ title: "New Outlook"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2362}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2361}
"WPFToggleNewOutlook": {
"Content": "New Outlook",
"Description": "If disabled it removes the toggle for new Outlook, disables the new Outlook migration and makes sure the Outlook Application actually uses the old Outlook.",

View File

@@ -3,7 +3,7 @@ title: "NumLock on Startup"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2204}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2203}
"WPFToggleNumLock": {
"Content": "NumLock on Startup",
"Description": "Toggle the Num Lock key state when your computer starts.",

View File

@@ -3,7 +3,7 @@ title: "S3 Sleep"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2563}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2567}
"WPFToggleS3Sleep": {
"Content": "S3 Sleep",
"Description": "Toggles between Modern Standby and S3 sleep.",

View File

@@ -3,7 +3,7 @@ title: "Show File Extensions"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2450}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2449}
"WPFToggleShowExt": {
"Content": "Show File Extensions",
"Description": "If enabled then File extensions (e.g., .txt, .jpg) are visible.",

View File

@@ -3,10 +3,10 @@ title: "Recommendations in Start Menu"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2248}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2247}
"WPFToggleStartMenuRecommendations": {
"Content": "Recommendations in Start Menu",
"Description": "If disabled then you will not see recommendations in the Start Menu.",
"Description": "If disabled then you will not see recommendations in the Start Menu. WARNING: This will also disable Windows Spotlight on your Lock Screen as a side effect.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",

View File

@@ -3,7 +3,7 @@ title: "Sticky Keys"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2344}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2343}
"WPFToggleStickyKeys": {
"Content": "Sticky Keys",
"Description": "If Enabled then Sticky Keys is activated - Sticky keys is an accessibility feature of some graphical user interfaces which assists users who have physical disabilities or help users reduce repetitive strain injury.",

View File

@@ -3,7 +3,7 @@ title: "Task View Button in Taskbar"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2496}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2495}
"WPFToggleTaskView": {
"Content": "Task View Button in Taskbar",
"Description": "If Enabled then Task View Button in Taskbar will be shown.",

View File

@@ -3,7 +3,7 @@ title: "Center Taskbar Items"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2514}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2513}
"WPFToggleTaskbarAlignment": {
"Content": "Center Taskbar Items",
"Description": "[Windows 11] If Enabled then the Taskbar Items will be shown on the Center, otherwise the Taskbar Items will be shown on the Left.",
@@ -25,6 +25,11 @@ description: ""
Invoke-WinUtilExplorerUpdate -action \"restart\"
"
],
"UndoScript": [
"
Invoke-WinUtilExplorerUpdate -action \"restart\"
"
],
```
## Registry Changes

View File

@@ -3,7 +3,7 @@ title: "Search Button in Taskbar"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2478}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2477}
"WPFToggleTaskbarSearch": {
"Content": "Search Button in Taskbar",
"Description": "If Enabled Search Button will be on the taskbar.",

View File

@@ -3,7 +3,7 @@ title: "Verbose Messages During Logon"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2230}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2229}
"WPFToggleVerboseLogon": {
"Content": "Verbose Messages During Logon",
"Description": "Show detailed messages during the login process for troubleshooting and diagnostics.",

View File

@@ -3,7 +3,7 @@ title: "Delete Temporary Files"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2039}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2038}
"WPFTweaksDeleteTempFiles": {
"Content": "Delete Temporary Files",
"Description": "Erases TEMP Folders",

View File

@@ -3,7 +3,7 @@ title: "Disable Explorer Automatic Folder Discovery"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2612}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2616}
"WPFTweaksDisableExplorerAutoDiscovery": {
"Content": "Disable Explorer Automatic Folder Discovery",
"Description": "Windows Explorer automatically tries to guess the type of the folder based on its contents, slowing down the browsing experience.",

View File

@@ -3,7 +3,7 @@ title: "Run Disk Cleanup"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2026}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2025}
"WPFTweaksDiskCleanup": {
"Content": "Run Disk Cleanup",
"Description": "Runs Disk Cleanup on Drive C: and removes old Windows Updates.",

View File

@@ -3,7 +3,7 @@ title: "Disable Windows Platform Binary Table (WPBT)"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1893}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1892}
"WPFTweaksWPBT": {
"Content": "Disable Windows Platform Binary Table (WPBT)",
"Description": "If enabled then allows your computer vendor to execute a program each time it boots. It enables computer vendors to force install anti-theft software, software drivers, or a software program conveniently. This could also be a security risk.",

View File

@@ -3,7 +3,7 @@ title: "Adobe Network Block"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1974}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1973}
"WPFTweaksBlockAdobeNet": {
"Content": "Adobe Network Block",
"Description": "Reduce user interruptions by selectively blocking connections to Adobe's activation and telemetry servers. Credit: Ruddernation-Designs",

View File

@@ -3,7 +3,7 @@ title: "Disable Background Apps"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2112}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2111}
"WPFTweaksDisableBGapps": {
"Content": "Disable Background Apps",
"Description": "Disables all Microsoft Store apps from running in the background, which has to be done individually since Win11",

View File

@@ -3,7 +3,7 @@ title: "Disable Fullscreen Optimizations"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2128}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2127}
"WPFTweaksDisableFSO": {
"Content": "Disable Fullscreen Optimizations",
"Description": "Disables FSO in all applications. NOTE: This will disable Color Management in Exclusive Fullscreen",

View File

@@ -3,7 +3,7 @@ title: "Disable IPv6"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2090}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2089}
"WPFTweaksDisableIPv6": {
"Content": "Disable IPv6",
"Description": "Disables IPv6.",

View File

@@ -3,7 +3,7 @@ title: "Disable Notification Tray/Calendar"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1951}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1950}
"WPFTweaksDisableNotifications": {
"Content": "Disable Notification Tray/Calendar",
"Description": "Disables all Notifications INCLUDING Calendar",

View File

@@ -3,7 +3,7 @@ title: "Prefer IPv4 over IPv6"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2052}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2051}
"WPFTweaksIPv46": {
"Content": "Prefer IPv4 over IPv6",
"Description": "To set the IPv4 preference can have latency and security benefits on private networks where IPv6 is not configured.",

View File

@@ -3,7 +3,7 @@ title: "Block Razer Software Installs"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1909}
```json {filename="config/tweaks.json",linenos=inline,linenostart=1908}
"WPFTweaksRazerBlock": {
"Content": "Block Razer Software Installs",
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software. WARNING: this will also block all Windows third-party driver installations.",

View File

@@ -78,7 +78,6 @@ description: ""
$Sid = (Get-LocalUser $Env:UserName).Sid.Value
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx\\AppxAllUserStore\\EndOfLife\\$Sid\\$Appx\" -Force
Remove-AppxPackage $Appx
}
"
],
"UndoScript": [

View File

@@ -3,7 +3,7 @@ title: "Set Classic Right-Click Menu "
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2004}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2003}
"WPFTweaksRightClickMenu": {
"Content": "Set Classic Right-Click Menu ",
"Description": "Great Windows 11 tweak to bring back good context menus when right clicking things in explorer.",

View File

@@ -3,7 +3,7 @@ title: "Disable Teredo"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2068}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2067}
"WPFTweaksTeredo": {
"Content": "Disable Teredo",
"Description": "Teredo network tunneling is a ipv6 feature that can cause additional latency, but may cause problems with some games",

View File

@@ -3,7 +3,7 @@ title: "DNS"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=2588}
```json {filename="config/tweaks.json",linenos=inline,linenostart=2592}
"WPFchangedns": {
"Content": "DNS",
"category": "z__Advanced Tweaks - CAUTION",

View File

@@ -15,9 +15,9 @@ function Get-WinUtilSelectedPackages
)
if ($PackageList.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
}
$packages = [System.Collections.Hashtable]::new()

View File

@@ -4,9 +4,9 @@ function Hide-WPFInstallAppBusy {
Hides the busy overlay in the install app area of the WPF form.
This is used to indicate that an install or uninstall has finished.
#>
$sync.form.Dispatcher.Invoke([action]{
Invoke-WPFUIThread -ScriptBlock {
$sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Collapsed
$sync.InstallAppAreaBorder.IsEnabled = $true
$sync.InstallAppAreaScrollViewer.Effect.Radius = 0
})
}
}

View File

@@ -113,7 +113,7 @@ function Install-WinUtilProgramChoco {
[int]$totalPrograms
)
$progressState = if ($currentIndex -eq $totalPrograms) { "Normal" } else { "Error" }
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) }
}
function Install-ChocoPackage {
@@ -234,7 +234,7 @@ function Install-WinUtilProgramChoco {
for ($currentIndex = 0; $currentIndex -lt $totalPrograms; $currentIndex++) {
$Program = $Programs[$currentIndex]
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($currentIndex / $totalPrograms * 100)
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)})
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)}
switch ($Action) {
"Install" {

View File

@@ -117,7 +117,7 @@ Function Install-WinUtilProgramWinget {
$Program = $Programs[$i]
$result = $false
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($i / $count * 100)
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i / $count)})
Invoke-WPFUIThread -ScriptBlock{ Set-WinUtilTaskbaritem -value ($i / $count)}
$result = switch ($Action) {
"Install" {Invoke-Install -Program $Program}

View File

@@ -8,7 +8,7 @@ function Invoke-WinUtilExplorerUpdate {
)
if ($action -eq "refresh") {
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
Invoke-WPFRunspace -ScriptBlock {
# Define the Win32 type only if it doesn't exist
if (-not ([System.Management.Automation.PSTypeName]'Win32').Type) {
Add-Type -TypeDefinition @"

View File

@@ -10,46 +10,40 @@ function Invoke-WinUtilFeatureInstall {
$CheckBox
)
$x = 0
$CheckBox | ForEach-Object {
if($sync.configs.feature.$psitem.feature) {
Foreach( $feature in $sync.configs.feature.$psitem.feature ) {
if($sync.configs.feature.$CheckBox.feature) {
Foreach( $feature in $sync.configs.feature.$CheckBox.feature ) {
try {
Write-Host "Installing $feature"
Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart
} catch {
if ($psitem.Exception.Message -like "*requires elevation*") {
if ($CheckBox.Exception.Message -like "*requires elevation*") {
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
} else {
Write-Warning "Unable to Install $feature due to unhandled exception"
Write-Warning $psitem.Exception.StackTrace
Write-Warning $CheckBox.Exception.StackTrace
}
}
}
}
if($sync.configs.feature.$psitem.InvokeScript) {
Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ) {
if($sync.configs.feature.$CheckBox.InvokeScript) {
Foreach( $script in $sync.configs.feature.$CheckBox.InvokeScript ) {
try {
$Scriptblock = [scriptblock]::Create($script)
Write-Host "Running Script for $psitem"
Write-Host "Running Script for $CheckBox"
Invoke-Command $scriptblock -ErrorAction stop
} catch {
if ($psitem.Exception.Message -like "*requires elevation*") {
if ($CheckBox.Exception.Message -like "*requires elevation*") {
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
} else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
Write-Warning "Unable to Install $feature due to unhandled exception"
Write-Warning $psitem.Exception.StackTrace
Write-Warning $CheckBox.Exception.StackTrace
}
}
}
}
$X++
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) })
}
}

View File

@@ -1,23 +0,0 @@
function Invoke-WinUtilGPU {
$gpuInfo = Get-CimInstance Win32_VideoController
# GPUs to blacklist from using Demanding Theming
$lowPowerGPUs = (
"*NVIDIA GeForce*M*",
"*NVIDIA GeForce*Laptop*",
"*NVIDIA GeForce*GT*",
"*AMD Radeon(TM)*",
"*Intel(R) HD Graphics*",
"*UHD*"
)
foreach ($gpu in $gpuInfo) {
foreach ($gpuPattern in $lowPowerGPUs) {
if ($gpu.Name -like $gpuPattern) {
return $false
}
}
}
return $true
}

View File

@@ -14,11 +14,15 @@ function Set-WinUtilProgressbar{
[int]$Percent
)
$sync.form.Dispatcher.Invoke([action]{$sync.progressBarTextBlock.Text = $label})
$sync.form.Dispatcher.Invoke([action]{$sync.progressBarTextBlock.ToolTip = $label})
if($PARAM_NOUI) {
return;
}
Invoke-WPFUIThread -ScriptBlock {$sync.progressBarTextBlock.Text = $label}
Invoke-WPFUIThread -ScriptBlock {$sync.progressBarTextBlock.ToolTip = $label}
if ($percent -lt 5 ) {
$percent = 5 # Ensure the progress bar is not empty, as it looks weird
}
$sync.form.Dispatcher.Invoke([action]{ $sync.ProgressBar.Value = $percent})
Invoke-WPFUIThread -ScriptBlock { $sync.ProgressBar.Value = $percent}
}

View File

@@ -10,12 +10,12 @@ function Show-WPFInstallAppBusy {
param (
$text = "Installing apps..."
)
$sync.form.Dispatcher.Invoke([action]{
Invoke-WPFUIThread -ScriptBlock {
$sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Visible
$sync.InstallAppAreaOverlay.Width = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4)
$sync.InstallAppAreaOverlay.Height = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4)
$sync.InstallAppAreaOverlayText.Text = $text
$sync.InstallAppAreaBorder.IsEnabled = $false
$sync.InstallAppAreaScrollViewer.Effect.Radius = 5
})
}
}

View File

@@ -18,6 +18,31 @@ function Invoke-WPFButton {
Set-WinUtilProgressBar -label "" -percent 0
}
# Check if button is defined in feature config with function or InvokeScript
if ($sync.configs.feature.$Button) {
$buttonConfig = $sync.configs.feature.$Button
# If button has a function defined, call it
if ($buttonConfig.function) {
$functionName = $buttonConfig.function
if (Get-Command $functionName -ErrorAction SilentlyContinue) {
& $functionName
return
}
}
# If button has InvokeScript defined, execute the scripts
if ($buttonConfig.InvokeScript -and $buttonConfig.InvokeScript.Count -gt 0) {
foreach ($script in $buttonConfig.InvokeScript) {
if (-not [string]::IsNullOrWhiteSpace($script)) {
Invoke-Expression $script
}
}
return
}
}
# Fallback to hard-coded switch for buttons not in feature.json
Switch -Wildcard ($Button) {
"WPFTab?BT" {Invoke-WPFTab $Button}
"WPFInstall" {Invoke-WPFInstall}
@@ -34,34 +59,14 @@ function Invoke-WPFButton {
"WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"}
"WPFRemoveUltPerf" {Invoke-WPFUltimatePerformance -State "Disable"}
"WPFundoall" {Invoke-WPFundoall}
"WPFFeatureInstall" {Invoke-WPFFeatureInstall}
"WPFPanelDISM" {Invoke-WPFSystemRepair}
"WPFPanelAutologin" {Invoke-WPFPanelAutologin}
"WPFPanelComputer" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelControl" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelNetwork" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelPower" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelPrinter" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelRegion" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelRestore" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelSound" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelSystem" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelTimedate" {Invoke-WPFControlPanel -Panel $button}
"WPFPanelUser" {Invoke-WPFControlPanel -Panel $button}
"WPFUpdatesdefault" {Invoke-WPFUpdatesdefault}
"WPFFixesUpdate" {Invoke-WPFFixesUpdate}
"WPFFixesWinget" {Invoke-WPFFixesWinget}
"WPFRunAdobeCCCleanerTool" {Invoke-WPFRunAdobeCCCleanerTool}
"WPFFixesNetwork" {Invoke-WPFFixesNetwork}
"WPFUpdatesdisable" {Invoke-WPFUpdatesdisable}
"WPFUpdatessecurity" {Invoke-WPFUpdatessecurity}
"WPFWinUtilShortcut" {Invoke-WPFShortcut -ShortcutToAdd "WinUtil" -RunAsAdmin $true}
"WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"}
"WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"}
"WPFCloseButton" {Invoke-WPFCloseButton}
"WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile}
"WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile}
"WPFWinUtilSSHServer" {Invoke-WPFSSHServer}
"WPFCloseButton" {$sync.Form.Close(); Write-Host "Bye bye!"}
"WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen}
"WPFToggleFOSSHighlight" {
if ($sync.WPFToggleFOSSHighlight.IsChecked) {

View File

@@ -1,12 +0,0 @@
function Invoke-WPFCloseButton {
<#
.SYNOPSIS
Close application
.PARAMETER Button
#>
$sync["Form"].Close()
Write-Host "Bye bye!"
}

View File

@@ -1,26 +0,0 @@
function Invoke-WPFControlPanel {
<#
.SYNOPSIS
Opens the requested legacy panel
.PARAMETER Panel
The panel to open
#>
param($Panel)
switch ($Panel) {
"WPFPanelControl" {control}
"WPFPanelComputer" {compmgmt.msc}
"WPFPanelNetwork" {ncpa.cpl}
"WPFPanelPower" {powercfg.cpl}
"WPFPanelPrinter" {Start-Process "shell:::{A8A91A66-3A7D-4424-8D24-04E180695C7A}"}
"WPFPanelRegion" {intl.cpl}
"WPFPanelRestore" {rstrui.exe}
"WPFPanelSound" {mmsys.cpl}
"WPFPanelSystem" {sysdm.cpl}
"WPFPanelTimedate" {timedate.cpl}
"WPFPanelUser" {control userpasswords2}
}
}

View File

@@ -12,21 +12,25 @@ function Invoke-WPFFeatureInstall {
return
}
$handle = Invoke-WPFRunspace -ScriptBlock {
$Features = $sync.selectedFeatures
Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock {
param($Features, $DebugPreference)
$sync.ProcessRunning = $true
if ($Features.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
}
Invoke-WinUtilFeatureInstall $Features
$x = 0
$Features | ForEach-Object {
Invoke-WinUtilFeatureInstall $Feature
$X++
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) }
}
$sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
Write-Host "==================================="
Write-Host "--- Features are Installed ---"

View File

@@ -20,13 +20,13 @@ function Invoke-WPFGetInstalled {
}
$managerPreference = $sync["ManagerPreference"]
Invoke-WPFRunspace -ParameterList @(("managerPreference", $managerPreference),("checkbox", $checkbox)) -DebugPreference $DebugPreference -ScriptBlock {
Invoke-WPFRunspace -ParameterList @(("managerPreference", $managerPreference),("checkbox", $checkbox)) -ScriptBlock {
param (
[string]$checkbox,
[PackageManagers]$managerPreference
)
$sync.ProcessRunning = $true
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Indeterminate" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" }
if ($checkbox -eq "winget") {
Write-Host "Getting Installed Programs..."
@@ -48,6 +48,6 @@ function Invoke-WPFGetInstalled {
Write-Host "Done..."
$sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" }
}
}

View File

@@ -71,9 +71,11 @@ function Invoke-WPFImpex {
# $flattenedJson = $jsonFile.PSObject.Properties.Where({ $_.Name -ne "Install" }).ForEach({ $_.Value })
$flattenedJson = $jsonFile
Update-WinUtilSelections -flatJson $flattenedJson
# TODO test with toggles
if (!$PARAM_NOUI) {
Reset-WPFCheckBoxes -doToggles $true
}
}
} catch {
Write-Error "An error occurred while importing: $_"
}

View File

@@ -1,13 +1,12 @@
function Invoke-WPFInstall {
param (
[Parameter(Mandatory=$false)]
[PSObject[]]$PackagesToInstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ })
)
<#
.SYNOPSIS
Installs the selected programs using winget, if one or more of the selected programs are already installed on the system, winget will try and perform an upgrade if there's a newer version to install.
#>
$PackagesToInstall = $sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ }
if($sync.ProcessRunning) {
$msg = "[Invoke-WPFInstall] An Install process is currently running."
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
@@ -22,8 +21,8 @@ function Invoke-WPFInstall {
$ManagerPreference = $sync["ManagerPreference"]
Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ManagerPreference", $ManagerPreference)) -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $ManagerPreference, $DebugPreference)
$handle = Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ManagerPreference", $ManagerPreference)) -ScriptBlock {
param($PackagesToInstall, $ManagerPreference)
$packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToInstall -Preference $ManagerPreference
@@ -45,12 +44,12 @@ function Invoke-WPFInstall {
Write-Host "==========================================="
Write-Host "-- Installs have finished ---"
Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
} catch {
Write-Host "==========================================="
Write-Host "Error: $_"
Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }
}
$sync.ProcessRunning = $False
}

View File

@@ -27,8 +27,7 @@ function Invoke-WPFRunspace {
Param (
$ScriptBlock,
$ArgumentList,
$ParameterList,
$DebugPreference
$ParameterList
)
# Create a PowerShell instance
@@ -41,7 +40,7 @@ function Invoke-WPFRunspace {
foreach ($parameter in $ParameterList) {
$script:powershell.AddParameter($parameter[0], $parameter[1])
}
$script:powershell.AddArgument($DebugPreference) # Pass DebugPreference to the script block
$script:powershell.RunspacePool = $sync.runspace
# Execute the RunspacePool

View File

@@ -6,7 +6,7 @@ function Invoke-WPFSSHServer {
#>
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
Invoke-WPFRunspace -ScriptBlock {
Invoke-WinUtilSSHServer

View File

@@ -2,13 +2,15 @@ function Invoke-WPFSystemRepair {
<#
.SYNOPSIS
Checks for system corruption using SFC, and DISM
Checks for disk failure using Chkdsk
.DESCRIPTION
1. SFC - Fixes system file corruption, and fixes DISM if it was corrupted
2. DISM - Fixes system image corruption, and fixes SFC's system image if it was corrupted
3. Chkdsk - Checks for disk errors, which can cause system file corruption and notifies of early disk failure
1. Chkdsk - Checks for disk errors, which can cause system file corruption and notifies of early disk failure
2. SFC - scans protected system files for corruption and fixes them
3. DISM - Repair a corrupted Windows operating system image
#>
Start-Process cmd.exe -ArgumentList "/c chkdsk.exe /scan /perf" -NoNewWindow -Wait
Start-Process cmd.exe -ArgumentList "/c chkdsk /scan /perf" -NoNewWindow -Wait
Start-Process cmd.exe -ArgumentList "/c sfc /scannow" -NoNewWindow -Wait
Start-Process cmd.exe -ArgumentList "/c dism /online /cleanup-image /restorehealth" -NoNewWindow -Wait

View File

@@ -0,0 +1,21 @@
function Invoke-WPFUIThread {
<#
.SYNOPSIS
Creates and runs a task on Winutil's WPF Forms thread.
.PARAMETER ScriptBlock
The scriptblock to invoke in the thread
#>
[CmdletBinding()]
Param (
$ScriptBlock
)
if ($PARAM_NOUI) {
return;
}
$sync.form.Dispatcher.Invoke([action]$ScriptBlock)
}

View File

@@ -32,8 +32,8 @@ function Invoke-WPFUnInstall {
$ManagerPreference = $sync["ManagerPreference"]
Invoke-WPFRunspace -ParameterList @(("PackagesToUninstall", $PackagesToUninstall),("ManagerPreference", $ManagerPreference)) -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToUninstall, $ManagerPreference, $DebugPreference)
Invoke-WPFRunspace -ParameterList @(("PackagesToUninstall", $PackagesToUninstall),("ManagerPreference", $ManagerPreference)) -ScriptBlock {
param($PackagesToUninstall, $ManagerPreference)
$packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToUninstall -Preference $ManagerPreference
$packagesWinget = $packagesSorted[[PackageManagers]::Winget]
@@ -54,12 +54,12 @@ function Invoke-WPFUnInstall {
Write-Host "==========================================="
Write-Host "-- Uninstalls have finished ---"
Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
} catch {
Write-Host "==========================================="
Write-Host "Error: $_"
Write-Host "==========================================="
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" }
}
$sync.ProcessRunning = $False

View File

@@ -25,30 +25,27 @@ function Invoke-WPFtweaksbutton {
Write-Debug "Number of tweaks to process: $($Tweaks.Count)"
# The leading "," in the ParameterList is necessary because we only provide one argument and powershell cannot be convinced that we want a nested loop with only one argument otherwise
Invoke-WPFRunspace -ParameterList @(,("tweaks",$tweaks)) -DebugPreference $DebugPreference -ScriptBlock {
param(
$tweaks,
$DebugPreference
)
$handle = Invoke-WPFRunspace -ParameterList @(,("tweaks",$tweaks)) -ScriptBlock {
param($tweaks)
Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)"
$sync.ProcessRunning = $true
if ($Tweaks.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
}
# Execute other selected tweaks
for ($i = 0; $i -lt $Tweaks.Count; $i++) {
Set-WinUtilProgressBar -Label "Applying $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100)
Invoke-WinUtilTweaks $tweaks[$i]
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$Tweaks.Count) })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($i/$Tweaks.Count) }
}
Set-WinUtilProgressBar -Label "Tweaks finished" -Percent 100
$sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
Write-Host "================================="
Write-Host "-- Tweaks are Finished ---"
Write-Host "================================="

View File

@@ -20,26 +20,26 @@ function Invoke-WPFundoall {
return
}
Invoke-WPFRunspace -ArgumentList $tweaks -DebugPreference $DebugPreference -ScriptBlock {
param($tweaks, $DebugPreference)
Invoke-WPFRunspace -ArgumentList $tweaks -ScriptBlock {
param($tweaks)
$sync.ProcessRunning = $true
if ($tweaks.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
} else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }
}
for ($i = 0; $i -lt $tweaks.Count; $i++) {
Set-WinUtilProgressBar -Label "Undoing $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100)
Invoke-WinUtiltweaks $tweaks[$i] -undo $true
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$tweaks.Count) })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($i/$tweaks.Count) }
}
Set-WinUtilProgressBar -Label "Undo Tweaks Finished" -Percent 100
$sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" }
Write-Host "=================================="
Write-Host "--- Undo Tweaks are Finished ---"
Write-Host "=================================="

View File

@@ -0,0 +1,48 @@
function Invoke-WinUtilAutoRun {
<#
.SYNOPSIS
Runs Install, Tweaks, and Features with optional UI invocation.
#>
function BusyWait {
Start-Sleep -Seconds 5
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
}
BusyWait
Write-Host "Applying tweaks..."
Invoke-WPFtweaksbutton
BusyWait
Write-Host "Applying toggles..."
$handle = Invoke-WPFRunspace -ScriptBlock {
$Toggles = $sync.selectedToggles
Write-Debug "Inside Number of toggles to process: $($Toggles.Count)"
$sync.ProcessRunning = $true
for ($i = 0; $i -lt $Tweaks.Count; $i++) {
Invoke-WinUtilTweaks $Toggles[$i]
}
$sync.ProcessRunning = $false
Write-Host "================================="
Write-Host "-- Toggles are Finished ---"
Write-Host "================================="
}
BusyWait
Write-Host "Applying features..."
Invoke-WPFFeatureInstall
BusyWait
Write-Host "Installing applications..."
Invoke-WPFInstall
BusyWait
Write-Host "Done."
}

View File

@@ -13,10 +13,14 @@ $maxthreads = [int]$env:NUMBER_OF_PROCESSORS
# Create a new session state for parsing variables into our runspace
$hashVars = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync',$sync,$Null
$debugVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'DebugPreference',$DebugPreference,$Null
$uiVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'PARAM_NOUI',$PARAM_NOUI,$Null
$InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
# Add the variable to the session state
$InitialSessionState.Variables.Add($hashVars)
$InitialSessionState.Variables.Add($debugVar)
$InitialSessionState.Variables.Add($uiVar)
# Get every private function and add them to the session state
$functions = Get-ChildItem function:\ | Where-Object { $_.Name -imatch 'winutil|WPF' }
@@ -55,6 +59,42 @@ class GenericException : Exception {
GenericException($Message) : base($Message) {}
}
# Load the configuration files
$sync.configs.applicationsHashtable = @{}
$sync.configs.applications.PSObject.Properties | ForEach-Object {
$sync.configs.applicationsHashtable[$_.Name] = $_.Value
}
Set-PackageManagerPreference
if ($PARAM_NOUI) {
Show-CTTLogo
if ($PARAM_CONFIG -and -not [string]::IsNullOrWhiteSpace($PARAM_CONFIG)) {
Write-Host "Running config file tasks..."
Invoke-WPFImpex -type "import" -Config $PARAM_CONFIG
if ($PARAM_RUN) {
Invoke-WinUtilAutoRun
}
else {
Write-Host "Did you forget to add '--Run'?";
}
$sync.runspace.Dispose()
$sync.runspace.Close()
[System.GC]::Collect()
Stop-Transcript
exit 1
}
else {
Write-Host "Cannot automatically run without a config file provided."
$sync.runspace.Dispose()
$sync.runspace.Close()
[System.GC]::Collect()
Stop-Transcript
exit 1
}
}
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
@@ -115,12 +155,7 @@ $sync.Form.Add_Loaded({
})
Invoke-WinutilThemeChange -init $true
# Load the configuration files
$sync.configs.applicationsHashtable = @{}
$sync.configs.applications.PSObject.Properties | ForEach-Object {
$sync.configs.applicationsHashtable[$_.Name] = $_.Value
}
# Now call the function with the final merged config
Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1
@@ -144,7 +179,6 @@ $xaml.SelectNodes("//*[@Name]") | ForEach-Object {$sync["$("$($psitem.Name)")"]
#Persist Package Manager preference across winutil restarts
$sync.ChocoRadioButton.Add_Checked({Set-PackageManagerPreference Choco})
$sync.WingetRadioButton.Add_Checked({Set-PackageManagerPreference Winget})
Set-PackageManagerPreference
switch ($sync["ManagerPreference"]) {
"Choco" {$sync.ChocoRadioButton.IsChecked = $true; break}
@@ -341,45 +375,11 @@ $sync["Form"].Add_ContentRendered({
$sync["Form"].Focus()
# maybe this is not the best place to load and execute config file?
# maybe community can help?
if ($PARAM_CONFIG -and -not [string]::IsNullOrWhiteSpace($PARAM_CONFIG)) {
Write-Host "Running config file tasks..."
Invoke-WPFImpex -type "import" -Config $PARAM_CONFIG
if ($PARAM_RUN) {
# Wait for any existing process to complete before starting
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
Start-Sleep -Seconds 5
Write-Host "Applying tweaks..."
if (-not $sync.ProcessRunning) {
Invoke-WPFtweaksbutton
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
}
Start-Sleep -Seconds 5
Write-Host "Installing features..."
if (-not $sync.ProcessRunning) {
Invoke-WPFFeatureInstall
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 5
}
}
Start-Sleep -Seconds 5
Write-Host "Installing applications..."
if (-not $sync.ProcessRunning) {
Invoke-WPFInstall
while ($sync.ProcessRunning) {
Start-Sleep -Seconds 1
}
}
Start-Sleep -Seconds 5
Write-Host "Done."
Invoke-WinUtilAutoRun
}
}

View File

@@ -7,16 +7,11 @@
#>
param (
[switch]$Debug,
[string]$Config,
[switch]$Run
[switch]$Run,
[switch]$Noui
)
# Set DebugPreference based on the -Debug switch
if ($Debug) {
$DebugPreference = "Continue"
}
if ($Config) {
$PARAM_CONFIG = $Config
}
@@ -24,10 +19,14 @@ if ($Config) {
$PARAM_RUN = $false
# Handle the -Run switch
if ($Run) {
Write-Host "Running config file tasks..."
$PARAM_RUN = $true
}
$PARAM_NOUI = $false
if ($Noui) {
$PARAM_NOUI = $true
}
# Load DLLs
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Windows.Forms

View File

@@ -1,9 +1,7 @@
<#
.DESCRIPTION
Generates Hugo-compatible markdown files for the development documentation
based on config/tweaks.json and config/feature.json.
Each JSON entry gets its own .md file with the raw JSON snippet or PowerShell function embedded.
Called by the GitHub Actions docs workflow before Hugo build.
Generates Hugo markdown docs from config/tweaks.json and config/feature.json.
Run by the GitHub Actions docs workflow before Hugo build.
#>
function Update-Progress {
@@ -18,11 +16,7 @@ function Update-Progress {
}
function Get-RawJsonBlock {
<#
.SYNOPSIS
Extracts the raw JSON text for a specific item from a JSON file's lines.
Returns the line number and raw text, excluding the "link" property and closing brace.
#>
# Returns the raw JSON text and 1-based start line for an item, excluding the "link" property.
param (
[Parameter(Mandatory)]
[string]$ItemName,
@@ -35,7 +29,6 @@ function Get-RawJsonBlock {
$startIndex = -1
$startIndent = ""
# Find the line containing "ItemName": {
for ($i = 0; $i -lt $JsonLines.Count; $i++) {
if ($JsonLines[$i] -match "^(\s*)`"$escapedName`"\s*:\s*\{") {
$startIndex = $i
@@ -49,7 +42,6 @@ function Get-RawJsonBlock {
return $null
}
# Find the closing } at the same indentation level
$escapedIndent = [regex]::Escape($startIndent)
$endIndex = -1
for ($i = ($startIndex + 1); $i -lt $JsonLines.Count; $i++) {
@@ -64,7 +56,7 @@ function Get-RawJsonBlock {
return $null
}
# Walk backwards from closing brace to exclude "link" property and empty lines
# Strip trailing "link" property and blank lines before returning
$lastContentIndex = $endIndex - 1
while ($lastContentIndex -gt $startIndex) {
$trimmed = $JsonLines[$lastContentIndex].Trim()
@@ -75,28 +67,21 @@ function Get-RawJsonBlock {
}
}
$rawLines = $JsonLines[$startIndex..$lastContentIndex]
$rawText = $rawLines -join "`r`n"
return @{
LineNumber = $startIndex + 1 # 1-based
RawText = $rawText
LineNumber = $startIndex + 1
RawText = ($JsonLines[$startIndex..$lastContentIndex] -join "`r`n")
}
}
function Get-ButtonFunctionMapping {
<#
.SYNOPSIS
Parses Invoke-WPFButton.ps1 to build a hashtable mapping button names to function names.
#>
# Parses Invoke-WPFButton.ps1 and returns a hashtable of button name -> function name.
param (
[Parameter(Mandatory)]
[string]$ButtonFilePath
)
$mapping = @{}
$lines = Get-Content -Path $ButtonFilePath
foreach ($line in $lines) {
foreach ($line in (Get-Content -Path $ButtonFilePath)) {
if ($line -match '^\s*"(\w+)"\s*\{(Invoke-\w+)') {
$mapping[$matches[1]] = $matches[2]
}
@@ -105,11 +90,8 @@ function Get-ButtonFunctionMapping {
}
function Add-LinkAttributeToJson {
<#
.SYNOPSIS
Updates the "link" property on each top-level entry in a JSON config file
to point to the corresponding documentation page URL.
#>
# Updates only the "link" property for each entry in a JSON config file.
# Reads via ConvertFrom-Json for metadata, then edits lines directly to avoid reformatting.
param (
[Parameter(Mandatory)]
[string]$JsonFilePath,
@@ -119,32 +101,74 @@ function Add-LinkAttributeToJson {
[string]$ItemNameToCut
)
$jsonText = Get-Content -Path $JsonFilePath -Raw
$jsonData = $jsonText | ConvertFrom-Json
$jsonData = Get-Content -Path $JsonFilePath -Raw | ConvertFrom-Json
$lines = [System.Collections.Generic.List[string]](Get-Content -Path $JsonFilePath)
foreach ($item in $jsonData.PSObject.Properties) {
$itemName = $item.Name
$itemDetails = $item.Value
$category = $itemDetails.category -replace '[^a-zA-Z0-9]', '-'
$category = $item.Value.category -replace '[^a-zA-Z0-9]', '-'
$displayName = $itemName -replace $ItemNameToCut, ''
$docLink = "$UrlPrefix/$($category.ToLower())/$($displayName.ToLower())"
$newLink = "$UrlPrefix/$($category.ToLower())/$($displayName.ToLower())"
$escapedName = [regex]::Escape($itemName)
$itemDetails | Add-Member -NotePropertyName "link" -NotePropertyValue $docLink -Force
# Find item start line
$startIdx = -1
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match "^\s*`"$escapedName`"\s*:\s*\{") {
$startIdx = $i
break
}
}
if ($startIdx -eq -1) { continue }
# Derive indentation: propIndent is one level deeper than the item start.
# Used to target only top-level properties and skip nested object braces.
$null = $lines[$startIdx] -match '^(\s*)'
$propIndent = $matches[1] + ' '
$propIndentLen = $propIndent.Length
$escapedPropIndent = [regex]::Escape($propIndent)
# Scan forward: update existing "link" or find the closing brace to insert one.
# Closing brace is matched by indent <= propIndentLen to handle inconsistent formatting.
$linkUpdated = $false
$closeBraceIdx = -1
for ($j = $startIdx + 1; $j -lt $lines.Count; $j++) {
if ($lines[$j] -match "^$escapedPropIndent`"link`"\s*:") {
$lines[$j] = $lines[$j] -replace '"link"\s*:\s*"[^"]*"', "`"link`": `"$newLink`""
$linkUpdated = $true
break
}
if ($lines[$j] -match '^\s*\}') {
$null = $lines[$j] -match '^(\s*)'
if ($matches[1].Length -le $propIndentLen) {
$closeBraceIdx = $j
break
}
}
}
$jsonText = ($jsonData | ConvertTo-Json -Depth 100).replace('\n', "`n").replace('\r', "`r")
Set-Content -Path $JsonFilePath -Value $jsonText -Encoding utf8
if (-not $linkUpdated -and $closeBraceIdx -ne -1) {
# Insert "link" before the closing brace
$prevPropIdx = $closeBraceIdx - 1
while ($prevPropIdx -gt $startIdx -and $lines[$prevPropIdx].Trim() -eq '') { $prevPropIdx-- }
if ($lines[$prevPropIdx] -notmatch ',\s*$') {
$lines[$prevPropIdx] = $lines[$prevPropIdx].TrimEnd() + ','
}
$lines.Insert($closeBraceIdx, "$propIndent`"link`": `"$newLink`"")
}
}
Set-Content -Path $JsonFilePath -Value $lines -Encoding utf8
}
# ==============================================================================
# Main Script
# Main
# ==============================================================================
# Use PSScriptRoot if available (running as a script file), otherwise assume CWD is tools/
$scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { (Get-Location).Path }
$repoRoot = Resolve-Path "$scriptDir/.."
# Paths
$tweaksJsonPath = "$repoRoot/config/tweaks.json"
$featuresJsonPath = "$repoRoot/config/feature.json"
$tweaksOutputDir = "$repoRoot/docs/content/dev/tweaks"
@@ -155,7 +179,7 @@ $privateFunctionsDir = "$repoRoot/functions/private"
$itemnametocut = 'WPF(WinUtil|Toggle|Features?|Tweaks?|Panel|Fix(es)?)?'
$baseUrl = "https://winutil.christitus.com"
# Categories that should have generated documentation
# Categories with generated docs
$documentedCategories = @(
"Essential Tweaks",
"z__Advanced Tweaks - CAUTION",
@@ -163,49 +187,44 @@ $documentedCategories = @(
"Performance Plans",
"Features",
"Fixes",
"Legacy Windows Panels"
"Legacy Windows Panels",
"Powershell Profile Powershell 7+ Only",
"Remote Access"
)
# --- Load data ---
# Categories where Button entries embed a PS function instead of raw JSON
$functionEmbedCategories = @(
"Fixes",
"Powershell Profile Powershell 7+ Only",
"Remote Access"
)
Update-Progress "Loading JSON files" 10
$tweaks = Get-Content -Path $tweaksJsonPath -Raw | ConvertFrom-Json
$features = Get-Content -Path $featuresJsonPath -Raw | ConvertFrom-Json
# --- Load function files (content + relative path) ---
Update-Progress "Loading function files" 20
$functionFiles = @{}
Get-ChildItem -Path $publicFunctionsDir -Filter *.ps1 | ForEach-Object {
$functionFiles[$_.BaseName] = @{
Content = (Get-Content -Path $_.FullName -Raw).TrimEnd()
RelativePath = "functions/public/$($_.Name)"
}
$functionFiles[$_.BaseName] = @{ Content = (Get-Content -Path $_.FullName -Raw).TrimEnd(); RelativePath = "functions/public/$($_.Name)" }
}
Get-ChildItem -Path $privateFunctionsDir -Filter *.ps1 | ForEach-Object {
$functionFiles[$_.BaseName] = @{
Content = (Get-Content -Path $_.FullName -Raw).TrimEnd()
RelativePath = "functions/private/$($_.Name)"
}
$functionFiles[$_.BaseName] = @{ Content = (Get-Content -Path $_.FullName -Raw).TrimEnd(); RelativePath = "functions/private/$($_.Name)" }
}
# --- Build button-to-function mapping ---
Update-Progress "Building button-to-function mapping" 30
$buttonFunctionMap = Get-ButtonFunctionMapping -ButtonFilePath "$publicFunctionsDir/Invoke-WPFButton.ps1"
# --- Update link attributes in JSON files ---
Update-Progress "Updating documentation links in JSON" 40
Add-LinkAttributeToJson -JsonFilePath $tweaksJsonPath -UrlPrefix "$baseUrl/dev/tweaks" -ItemNameToCut $itemnametocut
Add-LinkAttributeToJson -JsonFilePath $featuresJsonPath -UrlPrefix "$baseUrl/dev/features" -ItemNameToCut $itemnametocut
# Reload JSON lines after link update (so line numbers are accurate)
# Reload lines after link update so line numbers in docs are accurate
$tweaksLines = Get-Content -Path $tweaksJsonPath
$featuresLines = Get-Content -Path $featuresJsonPath
# ==============================================================================
# Clean up old generated .md files (keep _index.md)
# Clean up old generated .md files (preserve _index.md)
# ==============================================================================
Update-Progress "Cleaning up old generated docs" 45
@@ -236,16 +255,12 @@ foreach ($itemName in $tweakNames) {
$categoryDir = "$tweaksOutputDir/$category"
$filename = "$categoryDir/$displayName.md"
if (-Not (Test-Path -Path $categoryDir)) {
New-Item -ItemType Directory -Path $categoryDir | Out-Null
}
if (-Not (Test-Path -Path $categoryDir)) { New-Item -ItemType Directory -Path $categoryDir | Out-Null }
# Hugo frontmatter
$title = $item.Content -replace '"', '\"'
$content = "---`r`ntitle: `"$title`"`r`ndescription: `"`"`r`n---`r`n`r`n"
if ($item.Type -eq "Button") {
# Button-type tweak: embed the mapped PowerShell function
$funcName = $buttonFunctionMap[$itemName]
if ($funcName -and $functionFiles.ContainsKey($funcName)) {
$func = $functionFiles[$funcName]
@@ -254,7 +269,6 @@ foreach ($itemName in $tweakNames) {
$content += "```````r`n"
}
} else {
# Standard tweak: embed raw JSON block
$jsonBlock = Get-RawJsonBlock -ItemName $itemName -JsonLines $tweaksLines
if ($jsonBlock) {
$content += "``````json {filename=`"config/tweaks.json`",linenos=inline,linenostart=$($jsonBlock.LineNumber)}`r`n"
@@ -262,27 +276,16 @@ foreach ($itemName in $tweakNames) {
$content += "```````r`n"
}
# Registry Changes section
if ($item.registry) {
$content += "`r`n## Registry Changes`r`n`r`n"
$content += "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.`r`n`r`n"
$content += "You can find information about the registry on [Wikipedia](https://www.wikiwand.com/en/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).`r`n"
}
# Service function reference
if ($item.service -and $functionFiles.ContainsKey("Set-WinUtilService")) {
$svcFunc = $functionFiles["Set-WinUtilService"]
$content += "#Function`r`n"
$content += "``````powershell {filename=`"$($svcFunc.RelativePath)`",linenos=inline,linenostart=1}`r`n"
$content += $svcFunc.Content + "`r`n"
$content += "```````r`n"
}
}
Set-Content -Path $filename -Value $content -Encoding utf8 -NoNewline
$percent = 50 + [int](($tweakCount / $totalTweaks) * 20)
if ($percent -gt 70) { $percent = 70 }
$percent = [Math]::Min(70, 50 + [int](($tweakCount / $totalTweaks) * 20))
Update-Progress "Generating tweak documentation ($tweakCount/$totalTweaks)" $percent
}
@@ -301,8 +304,6 @@ foreach ($itemName in $featureNames) {
$featureCount++
if ($item.category -notin $documentedCategories) { continue }
# Skip pure UI buttons that don't need docs
if ($itemName -eq "WPFFeatureInstall") { continue }
$category = $item.category -replace '[^a-zA-Z0-9]', '-'
@@ -310,16 +311,13 @@ foreach ($itemName in $featureNames) {
$categoryDir = "$featuresOutputDir/$category"
$filename = "$categoryDir/$displayName.md"
if (-Not (Test-Path -Path $categoryDir)) {
New-Item -ItemType Directory -Path $categoryDir | Out-Null
}
if (-Not (Test-Path -Path $categoryDir)) { New-Item -ItemType Directory -Path $categoryDir | Out-Null }
$title = $item.Content -replace '"', '\"'
$content = "---`r`ntitle: `"$title`"`r`ndescription: `"`"`r`n---`r`n`r`n"
if ($item.category -eq "Fixes" -or $item.category -eq "Legacy Windows Panels") {
# Embed the PowerShell function file
$funcName = $buttonFunctionMap[$itemName]
if ($item.category -in $functionEmbedCategories) {
$funcName = if ($item.function) { $item.function } else { $buttonFunctionMap[$itemName] }
if ($funcName -and $functionFiles.ContainsKey($funcName)) {
$func = $functionFiles[$funcName]
$content += "``````powershell {filename=`"$($func.RelativePath)`",linenos=inline,linenostart=1}`r`n"
@@ -327,7 +325,6 @@ foreach ($itemName in $featureNames) {
$content += "```````r`n"
}
} else {
# Features category: embed raw JSON block
$jsonBlock = Get-RawJsonBlock -ItemName $itemName -JsonLines $featuresLines
if ($jsonBlock) {
$content += "``````json {filename=`"config/feature.json`",linenos=inline,linenostart=$($jsonBlock.LineNumber)}`r`n"
@@ -338,8 +335,7 @@ foreach ($itemName in $featureNames) {
Set-Content -Path $filename -Value $content -Encoding utf8 -NoNewline
$percent = 70 + [int](($featureCount / $totalFeatures) * 20)
if ($percent -gt 90) { $percent = 90 }
$percent = [Math]::Min(90, 70 + [int](($featureCount / $totalFeatures) * 20))
Update-Progress "Generating feature documentation ($featureCount/$totalFeatures)" $percent
}

View File

@@ -1203,7 +1203,7 @@
<Button Name="WPFstandard" Content=" Standard " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
<Button Name="WPFminimal" Content=" Minimal " 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=" Show Installed Apps " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
<Button Name="WPFGetInstalledTweaks" Content=" Get Installed Tweaks " Margin="2" Width="{DynamicResource ButtonWidth}" Height="{DynamicResource ButtonHeight}"/>
</StackPanel>
</StackPanel>