Compare commits

..

49 Commits

Author SHA1 Message Date
Chris Titus 5aa099f6e2 Fix missing dism metadata (#4516)
* Fix product key invalid and missing metadata on some isos

* Fix Gabi's broken light mode pr
2026-05-19 14:11:27 -05:00
github-actions[bot] 9d85eea4e5 Update sponsors in README (#4489)
Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>
2026-05-19 13:27:33 -05:00
Sree Sankar S c765ffb317 Add minimize button to WinUtil window (#4508) 2026-05-19 13:26:54 -05:00
Chris Titus 82f51b4bf1 chore: Update generated dev docs (#4515) 2026-05-19 13:26:45 -05:00
Gabi d44c013464 Changes windev.ps1's syntax (#4506)
* Changes windev.ps1's syntax

* Update windev.ps1
2026-05-19 13:26:32 -05:00
Chris Titus 753d47b9bc Merge branch 'main' into pr/gepardjaro/4503 (#4514) 2026-05-19 13:26:07 -05:00
Gabi 8034e85521 Remove Write-Debug (#4498)
* Update Invoke-WinUtilCurrentSystem.ps1

* Update Invoke-WinUtilFontScaling.ps1

* Update Invoke-WinUtilTweaks.ps1

* Update Reset-WPFCheckBoxes.ps1

* Update Set-Preferences.ps1

* Update Update-WinUtilSelections.ps1

* Update Invoke-WPFSelectedCheckboxesUpdate.ps1

* Update Invoke-WPFtweaksbutton.ps1

* Update main.ps1

* Update main.ps1

* Update main.ps1

* Update main.ps1

* Update main.ps1

* Merge branch 'main' into Remove-Write-Debug
2026-05-19 13:16:06 -05:00
Gabi a09736f9a8 Cleanup Get-WinUtilToggleStatus.ps1 (#4497)
* Cleanup Get-WinUtilToggleStatus.ps1

* Update Get-WinUtilToggleStatus.ps1

* Merge branch 'main' into patch-9

* Update Get-WinUtilToggleStatus.ps1
2026-05-19 13:13:27 -05:00
Gabi 24aaf9a3cf Cleanup Get-WinUtilSelectedPackages.ps1 and remove annoying messages (#4496)
* Cleanup Get-WinUtilSelectedPackages.ps1 and remove annoying messages

* Update Get-WinUtilSelectedPackages.ps1

* Update Get-WinUtilSelectedPackages.ps1

* Update Get-WinUtilSelectedPackages.ps1

* Merge branch 'main' into patch-8

* Update Get-WinUtilSelectedPackages.ps1

* Update Get-WinUtilSelectedPackages.ps1

* Update Get-WinUtilSelectedPackages.ps1

* Update Get-WinUtilSelectedPackages.ps1
2026-05-19 13:07:10 -05:00
Chris Titus f57b5f4ffa chore: Update generated dev docs (#4513) 2026-05-19 13:01:00 -05:00
Pinak Dhabu 32d24c8024 Add Game Mode toggle and fix MPO overlay for 25H2 (#4495) 2026-05-19 13:00:07 -05:00
Nazrul Islam 743f9e3783 Refactor: Secure literal search and defensive scope handling (#4492)
* Refactor: Secure literal search and defensive scope handling

* Refactor: Secure literal search for Tweaks Tab

* Merge branch 'ChrisTitusTech:main' into fix-search-security
2026-05-19 12:56:58 -05:00
Chris Titus 522c4471c0 chore: Update generated dev docs (#4512) 2026-05-19 12:42:19 -05:00
Gabi ea698f3791 Added WPFTweaksDisableBitLocker to tweaks.json (#4486)
* Added WPFTweaksDisableBitLocker to tweaks.json

* Update tweaks.json

* Update tweaks.json

* Update tweaks.json

* Merge branch 'main' into patch-6
2026-05-19 12:41:49 -05:00
Gabi 8ffd15c9f3 simplify Compile.ps1 by alot (#4484)
* Update Compile.ps1

* Delete tools/Invoke-Preprocessing.ps1

* Update .gitignore

* Update Compile.ps1

* Update Compile.ps1

* Update Compile.ps1

* Update Compile.ps1

* Update Compile.ps1

* Update .gitignore

* Update Compile.ps1

* Update Compile.ps1

* Update Compile.ps1

* Merge branch 'main' into patch-5
2026-05-19 12:40:02 -05:00
Gabi 6c1cb0caab Deleted unused functions (#4482)
* Delete functions/private/Get-LocalizedYesNo.ps1

* Delete functions/private/Get-WPFObjectName.ps1

* Merge branch 'main' into patch-4
2026-05-19 12:36:49 -05:00
Gabi bcafbe6234 CleanUp Invoke-WinUtilFeatureInstall.ps1 and fix typo (#4481)
* CleanUp Invoke-WinUtilFeatureInstall.ps1

* Update Invoke-WinUtilFeatureInstall.ps1

* Update feature.json
2026-05-19 12:34:04 -05:00
dependabot[bot] fb54380b8b Bump actions/github-script from 7 to 9 (#4510)
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '9'
  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-05-19 10:56:12 -05:00
Gabi 39f26133f4 Update pre-release.yaml (#4487) 2026-05-15 09:02:05 -05:00
Gabi 09695f10aa Fixed mpc-qt's description in applications.json (#4480) 2026-05-15 08:54:44 -05:00
tacostrange d1becc5310 Fixed typo - 'there' to 'their' (#4477)
* Fixed typo - 'there' to 'their'

* fix typo in tweaks.json from 'there' to 'their'
2026-05-15 08:54:03 -05:00
Copilot 543b8958ef Fix Actions script injection vulnerability in issue-slash-commands.yaml (#4493)
* Initial plan

* Fix Actions script injection vulnerability in issue-slash-commands.yaml

Agent-Logs-Url: https://github.com/ChrisTitusTech/winutil/sessions/94895aac-198f-40b6-af42-27fe0c646587

Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>
2026-05-14 18:13:02 -05:00
Sean (ANGRYxScotsman) c39c54c7c1 update theme (#4490) 2026-05-14 14:22:33 -05:00
Chris Titus d8193fd8ac chore: Update generated dev docs (#4475) 2026-05-12 13:07:48 -05:00
Chris Titus 25adabd622 update bug 2026-05-12 13:07:27 -05:00
Gabi 2d605f1875 Make WPFTweaksServices do what it says (#4466)
* Update tweaks.json

* Update tweaks.json
2026-05-12 13:06:46 -05:00
Gabi d46d324df8 Cleanup programs install (#4465)
* Cleanup programs install

* Update Install-WinUtilProgramChoco.ps1
2026-05-12 13:06:13 -05:00
Chris Titus 3e16817640 chore: Update generated dev docs (#4474) 2026-05-12 13:03:58 -05:00
Chris Titus d0b91d190a chore: Update generated dev docs (#4473) 2026-05-12 13:03:01 -05:00
Gabi bdbfdb6681 Fixed WPFTweaksRemoveGallery and WPFTweaksRemoveHome (#4464)
* Fixed WPFTweaksRemoveGallery not setting explorer launchto

* Update tweaks.json

* Update tweaks.json
2026-05-12 13:02:54 -05:00
Gabi 0154b749a4 Added WPFTweaksWindowsAI (#4461)
* Added WPFTweaksWindowsAI

* Update tweaks.json
2026-05-12 13:02:26 -05:00
jb49088 e6e44e3e04 Add Deskflow to applications (#4450)
* Add Deskflow to applications

* add: Include Deskflow in applications list

---------

Co-authored-by: Chris Titus <contact@christitus.com>
2026-05-12 13:01:42 -05:00
Gabi e6d8fdff75 fix import (#4447)
* Made -Config use Runspaces main.ps1

* Fix no-UI config autorun

* Skip empty no-UI autorun sections

* Update Invoke-WinUtilAutoRun.ps1

* Ignore blank DNS selection during autorun

* Update main.ps1

* Update Invoke-WPFRunspace.ps1

* Update Invoke-WPFRunspace.ps1

* Update Invoke-WinUtilAutoRun.ps1

* Update Invoke-WinUtilAutoRun.ps1

* Update Invoke-WPFtweaksbutton.ps1

* Update start.ps1

* Update main.ps1

* Update Invoke-WPFtweaksbutton.ps1

* Update Invoke-WPFRunspace.ps1

* Update _index.md

* Merge branch 'ChrisTitusTech:main' into patch-3

* Merge branch 'ChrisTitusTech:main' into patch-3
2026-05-12 12:58:46 -05:00
Gabi 6ba184bdeb Hide Windows Updates from setting menu when disabling updates (#4445)
* Update Invoke-WPFUpdatesdisable.ps1

* Update Invoke-WPFUpdatesdefault.ps1

* Update Invoke-WPFUpdatesdefault.ps1

* Merge branch 'ChrisTitusTech:main' into patch-1

* Merge branch 'ChrisTitusTech:main' into patch-1

* Update Invoke-WPFUpdatesdisable.ps1

* Update Invoke-WPFUpdatesdisable.ps1
2026-05-12 12:57:07 -05:00
Ivan Lepekha 6d6defc206 improve: Clearing Applications list (#4451)
* Less radical removal of apps

* Moving some applications to Selfhosted category

* Some more chess-boxing

* Document section is too small

* TG forks are too niche

* Floorp should be good

* feat: Add new multimedia tools and update existing application entries in applications.json

---------

Co-authored-by: Chris Titus <contact@christitus.com>
2026-05-12 12:54:23 -05:00
Chris Titus fa073f8475 chore: Update generated dev docs (#4472) 2026-05-12 12:19:19 -05:00
Gabi 63aecc0bee Make WPFTweaksDeBloat an essential tweak and add it to presets (#4458)
* Update tweaks.json

* Update preset.json
2026-05-12 12:18:42 -05:00
Gabi a0887783f8 fix allowing everyone to close issues (#4454)
* Update issue-slash-commands.yaml

* Update issue-slash-commands.yaml

* Update issue-slash-commands.yaml
2026-05-07 16:23:43 -05:00
Ivan Lepekha f3880b66bb feat: Update GH issue template for known issues (#4455)
* Add checkbox for known issues acknowledgment

Some people do not check the link

* typo fix

Updated checkbox type to checkboxes in bug report template.

* :zombie_sound:

* :zombie_sound_2:

* AAAAAAAAAAAAAAA

* I'm tired of testing commits

* :zombie_sound_1337:

Added a description to the read issues checkbox.

* my bad
2026-05-07 15:56:01 -05:00
Chris Titus aa636926fa chore: Update generated dev docs (#4457) 2026-05-07 15:53:01 -05:00
Gabi ec3166bdc6 Update Invoke-WinUtilInstallPSProfile.ps1 (#4456)
* Update Invoke-WinUtilInstallPSProfile.ps1

* Update Invoke-WinUtilUninstallPSProfile.ps1

* Update Invoke-WinUtilInstallPSProfile.ps1

* Update Invoke-WinUtilUninstallPSProfile.ps1
2026-05-07 15:52:20 -05:00
Gabi a3f57532b6 Cleanup winget upgrade (#4410)
* Update Update-WinUtilProgramWinget.ps1

* Delete functions/private/Update-WinUtilProgramWinget.ps1

* Delete functions/private/Get-WinUtilInstallerProcess.ps1

* Update Invoke-WPFInstallUpgrade.ps1

* Update Invoke-WPFInstallUpgrade.ps1

* Update Invoke-WPFInstallUpgrade.ps1

* Update Invoke-WPFInstallUpgrade.ps1

* Update Invoke-WPFInstallUpgrade.ps1

* Update Invoke-WPFInstallUpgrade.ps1
2026-05-05 15:16:39 -05:00
github-actions[bot] 3a7851b0f4 Update sponsors in README (#4387)
Co-authored-by: ChrisTitusTech <7896101+ChrisTitusTech@users.noreply.github.com>
2026-04-30 15:19:09 -05:00
Gabi 6fa73db245 Removed anythingllm from applications.json (#4428) 2026-04-30 15:18:07 -05:00
Chris Titus 184fe22a35 Cleanup: Delete all Scheduled Tasks related things (#4435)
* Delete functions/private/Set-WinUtilScheduledTask.ps1

* Update Invoke-WinUtilTweaks.ps1

* Update Invoke-WinUtilCurrentSystem.ps1

* waste of time

---------

Co-authored-by: Gabi <218829269+GabiNun2@users.noreply.github.com>
2026-04-30 15:16:27 -05:00
Gabi 9d4613d838 Strip unneccary surpassion from win11 creator (#4422)
* Update Invoke-WinUtilISO.ps1

* Update Invoke-WinUtilISOScript.ps1

* Update Invoke-WinUtilISOUSB.ps1

* Merge branch 'ChrisTitusTech:main' into patch-8
2026-04-30 14:58:07 -05:00
Gabi 10d83c5b20 Added tweaks_applied to issue temeplate (#4416)
* Update bug_report.yaml

* Merge branch 'ChrisTitusTech:main' into patch-5
2026-04-30 14:37:34 -05:00
Chris Titus 4065759ca0 chore: Update generated dev docs (#4434) 2026-04-30 12:46:57 -05:00
Chris Titus 97d5f7b850 feat: Add Brave debloat settings to tweaks.json (#4427)
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 12:46:12 -05:00
111 changed files with 1284 additions and 3846 deletions
+17 -1
View File
@@ -9,6 +9,15 @@ body:
- Remember, we only support Windows 11. If you encounter problems on Windows 10, please consider upgrading to Windows 11. - Remember, we only support Windows 11. If you encounter problems on Windows 10, please consider upgrading to Windows 11.
- For general questions, join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ). - For general questions, join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
- type: checkboxes
id: read_issues
attributes:
label: "I have read the known issues"
description: "You [better do](https://winutil.christitus.com/knownissues/), cause your issue can be already there"
options:
- label: Yes, I did
required: true
- type: dropdown - type: dropdown
id: affected_part id: affected_part
attributes: attributes:
@@ -29,8 +38,15 @@ body:
validations: validations:
required: true required: true
- type: textarea
id: tweaks_applied
attributes:
label: List the tweaks you applied before the issue occurred.
validations:
required: false
- type: textarea - type: textarea
id: error_output id: error_output
attributes: attributes:
label: Paste the full error output (if available) or Screenshot. label: Paste the full error output (if available) or Screenshot or Video.
placeholder: "Include any relevant logs or error messages." placeholder: "Include any relevant logs or error messages."
+54 -92
View File
@@ -15,101 +15,63 @@ jobs:
contents: read contents: read
steps: steps:
- run: echo "command=false" >> $GITHUB_ENV - 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;
- name: Check for /label command // Authorization check first — before any parsing of comment content
id: check_label_command if (!allowedUsers.includes(commenter)) {
run: | console.log(`User ${commenter} is not in the allowlist. Skipping.`);
if [[ "${{ contains(github.event.comment.body, '/label') }}" == "true" ]]; then return;
echo "command=true" >> $GITHUB_ENV }
LABEL_NAME=$(echo "${{ github.event.comment.body }}" | awk -F"/label" '/\/label/ { match($2, /'\''([^'\'']*)'\''/, arr); if (arr[1] != "") print arr[1] }')
echo "label_command=true" >> $GITHUB_ENV
echo "label_name=${LABEL_NAME}" >> $GITHUB_ENV
else
echo "label_command=false" >> $GITHUB_ENV
fi
- name: Check for /unlabel command // Read comment body as data, never interpolated into shell
id: check_unlabel_command const body = context.payload.comment.body;
run: | const issueNumber = context.issue.number;
if [[ "${{ contains(github.event.comment.body, '/unlabel') }}" == "true" ]]; then const owner = context.repo.owner;
echo "command=true" >> $GITHUB_ENV const repo = context.repo.repo;
UNLABEL_NAME=$(echo "${{ github.event.comment.body }}" | awk -F"/unlabel" '/\/unlabel/ { match($2, /'\''([^'\'']*)'\''/, arr); if (arr[1] != "") print arr[1] }')
echo "unlabel_command=true" >> $GITHUB_ENV
echo "unlabel_name=${UNLABEL_NAME}" >> $GITHUB_ENV
else
echo "unlabel_command=false" >> $GITHUB_ENV
fi
- name: Check for /close command // /label 'name' or /label name
id: check_close_command const labelMatch = body.match(/\/label\s+'([^']+)'|\/label\s+(\S+?)(?:\s|$)/);
run: | if (labelMatch) {
if [[ "${{ contains(github.event.comment.body, '/close') }}" == "true" ]]; then const labelName = (labelMatch[1] || labelMatch[2]).trim();
echo "command=true" >> $GITHUB_ENV console.log(`Adding label: ${labelName}`);
echo "close_command=true" >> $GITHUB_ENV await github.rest.issues.addLabels({
echo "reopen_command=false" >> $GITHUB_ENV owner, repo, issue_number: issueNumber,
else labels: [labelName],
echo "close_command=false" >> $GITHUB_ENV });
fi }
- name: Check for /open or /reopen command // /unlabel 'name' or /unlabel name
id: check_reopen_command const unlabelMatch = body.match(/\/unlabel\s+'([^']+)'|\/unlabel\s+(\S+?)(?:\s|$)/);
run: | if (unlabelMatch) {
if [[ "${{ contains(github.event.comment.body, '/open') }}" == "true" ]] || [[ "${{ contains(github.event.comment.body, '/reopen') }}" == "true" ]]; then const labelName = (unlabelMatch[1] || unlabelMatch[2]).trim();
echo "command=true" >> $GITHUB_ENV console.log(`Removing label: ${labelName}`);
echo "reopen_command=true" >> $GITHUB_ENV await github.rest.issues.removeLabel({
echo "close_command=false" >> $GITHUB_ENV owner, repo, issue_number: issueNumber,
else name: labelName,
echo "reopen_command=false" >> $GITHUB_ENV });
fi }
- name: Check if the user is allowed // /close (optionally with 'not planned')
id: check_user if (body.includes('/close')) {
if: env.command == 'true' const stateReason = body.includes('not planned') ? 'not_planned' : 'completed';
run: | console.log(`Closing issue (reason: ${stateReason})`);
ALLOWED_USERS=("ChrisTitusTech" "og-mrk" "Marterich" "MyDrift-user" "Real-MullaC" "CodingWonders" "GabiNun") await github.rest.issues.update({
if [[ " ${ALLOWED_USERS[@]} " =~ " ${{ github.event.comment.user.login }} " ]]; then owner, repo, issue_number: issueNumber,
echo "user=true" >> $GITHUB_ENV state: 'closed',
else state_reason: stateReason,
exit 0 });
fi }
- name: Close issue // /open or /reopen
if: env.close_command == 'true' if (body.includes('/open') || body.includes('/reopen')) {
env: console.log('Reopening issue');
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} await github.rest.issues.update({
ISSUE_NUMBER: ${{ github.event.issue.number }} owner, repo, issue_number: issueNumber,
run: | state: 'open',
echo Closing the issue... });
if [[ "${{ contains(github.event.comment.body, 'not planned') }}" == "true" ]]; then }
gh issue close $ISSUE_NUMBER --repo ${{ github.repository }} --reason 'not planned'
else
gh issue close $ISSUE_NUMBER --repo ${{ github.repository }}
fi
- name: Reopen issue
if: env.reopen_command == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
echo Reopening the issue...
gh issue reopen $ISSUE_NUMBER --repo ${{ github.repository }}
- name: Label issue
if: env.label_command == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
echo Labeling the issue...
gh issue edit $ISSUE_NUMBER --repo ${{ github.repository }} --add-label "${{ env.label_name }}"
- name: Remove labels
if: env.unlabel_command == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
echo Unlabeling the issue...
gh issue edit $ISSUE_NUMBER --repo ${{ github.repository }} --remove-label "${{ env.unlabel_name }}"
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
config/feature.json config/feature.json
labels: | labels: |
automated automated
documentation skip-changelog
- name: Check outputs - name: Check outputs
shell: bash shell: bash
-5
View File
@@ -11,9 +11,6 @@
winutil.pdb winutil.pdb
### Preprocessor Hashes ###
.preprocessor_hashes.json
### Windows ### ### Windows ###
# Folder config file # Folder config file
@@ -54,8 +51,6 @@ winutil.ps1
binary/ binary/
.preprocessor_hashes.json
# Hugo Files # Hugo Files
docs/public/ docs/public/
docs/.hugo_build.lock docs/.hugo_build.lock
+25 -119
View File
@@ -1,144 +1,50 @@
param ( param (
[switch]$Run, [switch]$Run
[string]$Arguments
) )
if ((Get-Item ".\winutil.ps1" -ErrorAction SilentlyContinue).IsReadOnly) { $OFS = "`r`n" # Makes it so we dont need to add -Raw to every Get-Content command
Remove-Item ".\winutil.ps1" -Force
}
$OFS = "`r`n"
$scriptname = "winutil.ps1"
$workingdir = $PSScriptRoot
# Variable to sync between runspaces # Variable to sync between runspaces
$sync = [Hashtable]::Synchronized(@{}) $sync = [Hashtable]::Synchronized(@{})
$sync.configs = @{} $sync.configs = @{}
function Update-Progress { # Create the script in memory.
param ( $script = [System.Collections.Generic.List[string]]::new()
[Parameter(Mandatory, position=0)]
[string]$StatusMessage,
[Parameter(Mandatory, position=1)] $script.Add(
[ValidateRange(0,100)] ((Get-Content -Path scripts\start.ps1) -replace '#{replaceme}', (Get-Date -Format 'yy.MM.dd'))
[int]$Percent,
[Parameter(position=2)]
[string]$Activity = "Compiling"
)
Write-Progress -Activity $Activity -Status $StatusMessage -PercentComplete $Percent
}
Update-Progress "Pre-req: Running Preprocessor..." 0
# Dot source the 'Invoke-Preprocessing' Function from 'tools/Invoke-Preprocessing.ps1' Script
$preprocessingFilePath = ".\tools\Invoke-Preprocessing.ps1"
. $preprocessingFilePath
$excludedFiles = @()
# Add directories only if they exist
if (Test-Path '.\.git\') { $excludedFiles += '.\.git\' }
if (Test-Path '.\binary\') { $excludedFiles += '.\binary\' }
# Add files that should always be excluded
$excludedFiles += @(
'.\.gitignore',
'.\.gitattributes',
'.\.github\CODEOWNERS',
'.\LICENSE',
"$preprocessingFilePath",
'*.png',
'.\.preprocessor_hashes.json'
) )
$msg = "Pre-req: Code Formatting" $script.Add((Get-ChildItem -Path functions -Recurse -File | Get-Content))
Invoke-Preprocessing -WorkingDir "$workingdir" -ExcludedFiles $excludedFiles -ProgressStatusMessage $msg
# Create the script in memory. Get-ChildItem config | ForEach-Object {
Update-Progress "Pre-req: Allocating Memory" 0 $obj = Get-Content -Path $_.FullName | ConvertFrom-Json
$script_content = [System.Collections.Generic.List[string]]::new()
Update-Progress "Adding: Version" 10 if ($_.Name -eq "applications.json") {
$script_content.Add($(Get-Content "scripts\start.ps1").replace('#{replaceme}',"$(Get-Date -Format yy.MM.dd)")) $fixed = [ordered]@{}
foreach ($p in $obj.PSObject.Properties) {
Update-Progress "Adding: Functions" 20 $fixed["WPFInstall$($p.Name)"] = $p.Value
Get-ChildItem "functions" -Recurse -File | ForEach-Object {
$script_content.Add($(Get-Content $psitem.FullName))
}
Update-Progress "Adding: Config *.json" 40
Get-ChildItem "config" | Where-Object {$psitem.extension -eq ".json"} | ForEach-Object {
$json = (Get-Content $psitem.FullName -Raw)
$jsonAsObject = $json | ConvertFrom-Json
# Add 'WPFInstall' as a prefix to every entry-name in 'applications.json' file
if ($psitem.Name -eq "applications.json") {
foreach ($appEntryName in $jsonAsObject.PSObject.Properties.Name) {
$appEntryContent = $jsonAsObject.$appEntryName
$jsonAsObject.PSObject.Properties.Remove($appEntryName)
$jsonAsObject | Add-Member -MemberType NoteProperty -Name "WPFInstall$appEntryName" -Value $appEntryContent
} }
$obj = [pscustomobject]$fixed
} }
# Line 90 requires no whitespace inside the here-strings, to keep formatting of the JSON in the final script. $json = $obj | ConvertTo-Json -Depth 10
$json = @"
$($jsonAsObject | ConvertTo-Json -Depth 3)
"@
$sync.configs.$($psitem.BaseName) = $json | ConvertFrom-Json $sync.configs[$_.BaseName] = $obj
$script_content.Add($(Write-Output "`$sync.configs.$($psitem.BaseName) = @'`r`n$json`r`n'@ `| ConvertFrom-Json" )) $script.Add("`$sync.configs.$($_.BaseName) = @'`r`n$json`r`n'@ | ConvertFrom-Json")
} }
# Read the entire XAML file as a single string, preserving line breaks # Read the entire XAML file as a single string, preserving line breaks
$xaml = Get-Content "$workingdir\xaml\inputXML.xaml" -Raw $xaml = Get-Content -Path xaml\inputXML.xaml
$script.Add('$inputXML = @''' + "`n" + $xaml + "`n" + '''@')
Update-Progress "Adding: Xaml " 90 $autounattendXml = Get-Content -Path tools\autounattend.xml
$script.Add("`$WinUtilAutounattendXml = @'`r`n$autounattendXml`r`n'@")
# Add the XAML content to $script_content using a here-string $script.Add((Get-Content -Path scripts\main.ps1))
$script_content.Add(@"
`$inputXML = @'
$xaml
'@
"@)
Update-Progress "Adding: autounattend.xml" 95 Set-Content -Path winutil.ps1 -Value $script
$autounattendRaw = Get-Content "$workingdir\tools\autounattend.xml" -Raw
# Strip XML comments (<!-- ... -->, including multi-line)
$autounattendRaw = [regex]::Replace($autounattendRaw, '<!--.*?-->', '', [System.Text.RegularExpressions.RegexOptions]::Singleline)
# Drop blank lines and trim trailing whitespace per line
$autounattendXml = ($autounattendRaw -split "`r?`n" |
Where-Object { $_.Trim() -ne '' } |
ForEach-Object { $_.TrimEnd() }) -join "`r`n"
$script_content.Add(@"
`$WinUtilAutounattendXml = @'
$autounattendXml
'@
"@)
$script_content.Add($(Get-Content "scripts\main.ps1")) if ($Run) {
.\Winutil.ps1
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
Update-Progress -Activity "Validating" -StatusMessage "Checking winutil.ps1 Syntax" -Percent 0
try {
Get-Command -Syntax .\winutil.ps1 | Out-Null
} catch {
Write-Warning "Syntax Validation for 'winutil.ps1' has failed"
Write-Host "$($Error[0])" -ForegroundColor Red
exit 1
}
Write-Progress -Activity "Validating" -Completed
if ($run) {
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\Winutil.ps1 $Arguments
break
} }
+1 -1
View File
@@ -76,7 +76,7 @@ You'll see a new file named `winutil.ps1`, which was created by `Compile.ps1` sc
These are the sponsors that help keep this project alive with monthly contributions. 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/partybrasil"><img src="https:&#x2F;&#x2F;github.com&#x2F;partybrasil.png" width="60px" alt="User avatar: Miguel Diaz" /></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/Di3Z1E"><img src="https:&#x2F;&#x2F;github.com&#x2F;Di3Z1E.png" width="60px" alt="User avatar: Di3Z1E" /></a><a href="https://github.com/AbdulVakeel"><img src="https:&#x2F;&#x2F;github.com&#x2F;AbdulVakeel.png" width="60px" alt="User avatar: Abdul Vakeel Software Engineer" /></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/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 -->
## 🏅 Thanks to all Contributors ## 🏅 Thanks to all Contributors
Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻.
+32 -2111
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -129,7 +129,7 @@
"link": "https://winutil.christitus.com/dev/features/features/sandbox" "link": "https://winutil.christitus.com/dev/features/features/sandbox"
}, },
"WPFFeatureInstall": { "WPFFeatureInstall": {
"Content": "Run Features", "Content": "Install Features",
"category": "Features", "category": "Features",
"panel": "1", "panel": "1",
"Type": "Button", "Type": "Button",
+2
View File
@@ -5,6 +5,7 @@
"WPFTweaksDisableExplorerAutoDiscovery", "WPFTweaksDisableExplorerAutoDiscovery",
"WPFTweaksWPBT", "WPFTweaksWPBT",
"WPFTweaksDVR", "WPFTweaksDVR",
"WPFTweaksDeBloat",
"WPFTweaksLocation", "WPFTweaksLocation",
"WPFTweaksServices", "WPFTweaksServices",
"WPFTweaksTelemetry", "WPFTweaksTelemetry",
@@ -16,6 +17,7 @@
], ],
"Minimal": [ "Minimal": [
"WPFTweaksConsumerFeatures", "WPFTweaksConsumerFeatures",
"WPFTweaksDeBloat",
"WPFTweaksWPBT", "WPFTweaksWPBT",
"WPFTweaksServices", "WPFTweaksServices",
"WPFTweaksTelemetry" "WPFTweaksTelemetry"
+162 -78
View File
@@ -174,7 +174,7 @@
}, },
"WPFTweaksServices": { "WPFTweaksServices": {
"Content": "Services - Set to Manual", "Content": "Services - Set to Manual",
"Description": "Turns a bunch of system services to manual that don't need to be running all the time. This is pretty harmless as if the service is needed, it will simply start on demand.", "Description": "Sets some services to Manual startup and adjusts the SvcHostSplitThresholdInKB registry value to better match system memory, which can significantly reduce the number of svchost.exe processes.",
"category": "Essential Tweaks", "category": "Essential Tweaks",
"panel": "1", "panel": "1",
"service": [ "service": [
@@ -193,16 +193,6 @@
"StartupType": "Manual", "StartupType": "Manual",
"OriginalType": "Automatic" "OriginalType": "Automatic"
}, },
{
"Name": "RemoteAccess",
"StartupType": "Disabled",
"OriginalType": "Disabled"
},
{
"Name": "RemoteRegistry",
"StartupType": "Disabled",
"OriginalType": "Disabled"
},
{ {
"Name": "StorSvc", "Name": "StorSvc",
"StartupType": "Manual", "StartupType": "Manual",
@@ -212,26 +202,6 @@
"Name": "SharedAccess", "Name": "SharedAccess",
"StartupType": "Disabled", "StartupType": "Disabled",
"OriginalType": "Automatic" "OriginalType": "Automatic"
},
{
"Name": "TermService",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "TroubleshootingSvc",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "seclogon",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "ssh-agent",
"StartupType": "Disabled",
"OriginalType": "Disabled"
} }
], ],
"InvokeScript": [ "InvokeScript": [
@@ -282,6 +252,55 @@
"Value": "0", "Value": "0",
"Type": "DWord", "Type": "DWord",
"OriginalValue": "<RemoveEntry>" "OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "BraveNewsDisabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "BraveTalkDisabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "TorDisabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "BraveP3AEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "UrlKeyedAnonymizedDataCollectionEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "SafeBrowsingExtendedReportingEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "MetricsReportingEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
} }
], ],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/bravedebloat" "link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/bravedebloat"
@@ -588,6 +607,19 @@
], ],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removeedge" "link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removeedge"
}, },
"WPFTweaksDisableBitLocker": {
"Content": "BitLocker - Disable",
"Description": "Disables BitLocker.",
"category": "Essential Tweaks",
"panel": "1",
"InvokeScript": [
"Disable-BitLocker -MountPoint $Env:SystemDrive"
],
"UndoScript": [
"Enable-BitLocker -MountPoint $Env:SystemDrive"
],
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/disablebitlocker"
},
"WPFTweaksUTC": { "WPFTweaksUTC": {
"Content": "Date & Time - Set Time to UTC", "Content": "Date & Time - Set Time to UTC",
"Description": "Essential for computers that are dual booting. Fixes the time sync with Linux systems.", "Description": "Essential for computers that are dual booting. Fixes the time sync with Linux systems.",
@@ -642,41 +674,28 @@
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removeonedrive" "link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removeonedrive"
}, },
"WPFTweaksRemoveHome": { "WPFTweaksRemoveHome": {
"Content": "File Explorer Home - Disable", "Content": "File Explorer Home and Gallery - Disable",
"Description": "Removes the Home from Explorer and sets This PC as default.", "Description": "Removes the Home and Gallery from Explorer and sets This PC as default.",
"category": "z__Advanced Tweaks - CAUTION", "category": "z__Advanced Tweaks - CAUTION",
"panel": "1", "panel": "1",
"InvokeScript": [ "registry": [
" {
Remove-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{f874310e-b6b7-47dc-bc84-b9e6b38f5903}\" "Path": "HKCU:\\Software\\Classes\\CLSID\\{f874310e-b6b7-47dc-bc84-b9e6b38f5903}",
Set-ItemProperty -Path \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\" -Name LaunchTo -Value 1 "Name": "System.IsPinnedToNameSpaceTree",
" "Value": "0",
], "Type": "DWord",
"UndoScript": [ "OriginalValue": "<RemoveEntry>"
" },
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{f874310e-b6b7-47dc-bc84-b9e6b38f5903}\" {
Set-ItemProperty -Path \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\" -Name LaunchTo -Value 0 "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
" "Name": "LaunchTo",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
}
], ],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removehome" "link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removehome"
}, },
"WPFTweaksRemoveGallery": {
"Content": "File Explorer Gallery - Disable",
"Description": "Removes the Gallery from Explorer and sets This PC as default.",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"InvokeScript": [
"
Remove-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{e88865ea-0e1c-4e20-9aa6-edcd0212c87c}\"
"
],
"UndoScript": [
"
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{e88865ea-0e1c-4e20-9aa6-edcd0212c87c}\"
"
],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removegallery"
},
"WPFTweaksDisplay": { "WPFTweaksDisplay": {
"Content": "Visual Effects - Set to Best Performance", "Content": "Visual Effects - Set to Best Performance",
"Description": "Sets the system preferences to performance. You can do this manually with sysdm.cpl as well.", "Description": "Sets the system preferences to performance. You can do this manually with sysdm.cpl as well.",
@@ -801,8 +820,8 @@
}, },
"WPFTweaksDeBloat": { "WPFTweaksDeBloat": {
"Content": "Unwanted Pre-Installed Apps - Remove", "Content": "Unwanted Pre-Installed Apps - Remove",
"Description": "This will remove a bunch of Windows pre-installed applications which most people dont want on there system.", "Description": "This will remove a bunch of Windows pre-installed applications which most people dont want on their system.",
"category": "z__Advanced Tweaks - CAUTION", "category": "Essential Tweaks",
"panel": "1", "panel": "1",
"appx": [ "appx": [
"Microsoft.WindowsFeedbackHub", "Microsoft.WindowsFeedbackHub",
@@ -838,7 +857,7 @@
} }
" "
], ],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/debloat" "link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/debloat"
}, },
"WPFTweaksRestorePoint": { "WPFTweaksRestorePoint": {
"Content": "Restore Point - Create", "Content": "Restore Point - Create",
@@ -912,32 +931,45 @@
], ],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/storage" "link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/storage"
}, },
"WPFTweaksRemoveCopilot": { "WPFTweaksWindowsAI": {
"Content": "Microsoft Copilot - Disable", "Content": "Windows AI - Disable",
"Description": "Removes Copilot AppXPackages and related ai packages", "Description": "Removes or disables all ai features and packages",
"category": "z__Advanced Tweaks - CAUTION", "category": "z__Advanced Tweaks - CAUTION",
"panel": "1", "panel": "1",
"registry": [
{
"Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
"Name": "SettingsPageVisibility",
"Value": "hide:aicomponents",
"Type": "String",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\WindowsNotepad",
"Name": "DisableAIFeatures",
"Value": 1,
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
}
],
"InvokeScript": [ "InvokeScript": [
" "
Get-AppxPackage -AllUsers *Copilot* | Remove-AppxPackage -AllUsers
Get-AppxPackage -AllUsers Microsoft.MicrosoftOfficeHub | Remove-AppxPackage -AllUsers
$Appx = (Get-AppxPackage MicrosoftWindows.Client.CoreAI).PackageFullName $Appx = (Get-AppxPackage MicrosoftWindows.Client.CoreAI).PackageFullName
$Sid = (Get-LocalUser $Env:UserName).Sid.Value $Sid = (Get-LocalUser $Env:UserName).Sid.Value
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx\\AppxAllUserStore\\EndOfLife\\$Sid\\$Appx\" -Force New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx\\AppxAllUserStore\\EndOfLife\\$Sid\\$Appx\" -Force
Get-AppxPackage -AllUsers *Copilot* | Remove-AppxPackage -AllUsers
Get-AppxPackage -AllUsers Microsoft.MicrosoftOfficeHub | Remove-AppxPackage -AllUsers
Remove-AppxPackage $Appx Remove-AppxPackage $Appx
Write-Host \"Copilot Removed\" Set-Service -Name WSAIFabricSvc -StartupType Disabled
Disable-WindowsOptionalFeature -FeatureName Recall -Online
Write-Host \"Windows AI Disabled\"
" "
], ],
"UndoScript": [ "link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/windowsai"
"
Write-Host \"Installing Copilot...\"
winget install --name Copilot --source msstore --accept-package-agreements --accept-source-agreements --silent
"
],
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/removecopilot"
}, },
"WPFTweaksWPBT": { "WPFTweaksWPBT": {
"Content": "Windows Platform Binary Table (WPBT) - Disable", "Content": "Windows Platform Binary Table (WPBT) - Disable",
@@ -1442,6 +1474,14 @@
"Type": "DWord", "Type": "DWord",
"OriginalValue": "5", "OriginalValue": "5",
"DefaultState": "true" "DefaultState": "true"
},
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers",
"Name": "DisableOverlays",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "false"
} }
], ],
"link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/multiplaneoverlay" "link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/multiplaneoverlay"
@@ -1722,6 +1762,50 @@
], ],
"link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/taskview" "link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/taskview"
}, },
"WPFToggleGameMode": {
"Content": "Game Mode",
"Description": "If enabled, Windows prioritizes gaming performance by allocating system resources. Disable for audio/video production to prevent interference.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",
"registry": [
{
"Path": "HKCU:\\Software\\Microsoft\\GameBar",
"Name": "AllowAutoGameMode",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "true"
},
{
"Path": "HKCU:\\Software\\Microsoft\\GameBar",
"Name": "AutoGameModeEnabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "true"
}
],
"link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/gamemode"
},
"WPFToggleLongPaths": {
"Content": "Enable Long Paths",
"Description": "Enables support for file paths longer than 260 characters.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",
"registry": [
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem",
"Name": "LongPathsEnabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "false"
}
],
"link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/longpaths"
},
"WPFOOSUbutton": { "WPFOOSUbutton": {
"Content": "O&O ShutUp10++ - Run", "Content": "O&O ShutUp10++ - Run",
"category": "z__Advanced Tweaks - CAUTION", "category": "z__Advanced Tweaks - CAUTION",
-8
View File
@@ -380,13 +380,6 @@ Update UI
"Value": "0", "Value": "0",
"OriginalValue": "1" "OriginalValue": "1"
} }
],
"ScheduledTask": [
{
"Name": "Microsoft\\Windows\\Autochk\\Proxy",
"State": "Disabled",
"OriginalState": "Enabled"
}
] ]
} }
} }
@@ -397,7 +390,6 @@ Update UI
- `Description`: What it does - `Description`: What it does
- `category`: Essential/Advanced/Customize - `category`: Essential/Advanced/Customize
- `registry`: Registry changes to make - `registry`: Registry changes to make
- `ScheduledTask`: Scheduled tasks to modify
- `service`: Services to change - `service`: Services to change
- `OriginalValue/State`: For undo functionality - `OriginalValue/State`: For undo functionality
@@ -5,11 +5,18 @@ description: ""
```powershell {filename="functions/private/Invoke-WinUtilInstallPSProfile.ps1",linenos=inline,linenostart=1} ```powershell {filename="functions/private/Invoke-WinUtilInstallPSProfile.ps1",linenos=inline,linenostart=1}
function Invoke-WinUtilInstallPSProfile { function Invoke-WinUtilInstallPSProfile {
if (-not (Get-Command wt)) {
if (Test-Path $Profile) { Write-Host "Windows Terminal not found installing..."
Rename-Item $Profile -NewName ($Profile + '.bak') Install-WinUtilWinget
winget install Microsoft.WindowsTerminal --source winget --silent
} }
Start-Process pwsh -ArgumentList '-Command "irm https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1 | iex"' if (-not (Get-Command pwsh)) {
Write-Host "Powershell 7 not found installing..."
Install-WinUtilWinget
winget install Microsoft.PowerShell --source winget --silent
}
wt new-tab pwsh -NoExit -Command "irm https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1 | iex"
} }
``` ```
@@ -5,12 +5,11 @@ description: ""
```powershell {filename="functions/private/Invoke-WinUtilUninstallPSProfile.ps1",linenos=inline,linenostart=1} ```powershell {filename="functions/private/Invoke-WinUtilUninstallPSProfile.ps1",linenos=inline,linenostart=1}
function Invoke-WinUtilUninstallPSProfile { function Invoke-WinUtilUninstallPSProfile {
if (Test-Path ($Profile + '.bak')) {
Remove-Item $Profile if (Test-Path ($Profile + ".bak")) {
Rename-Item ($Profile + '.bak') -NewName $Profile Move-Item -Path ($Profile + ".bak") -Destination $Profile
} } else {
else { Remove-Item -Path $Profile
Remove-Item $Profile
} }
Write-Host "Successfully uninstalled CTT PowerShell Profile." -ForegroundColor Green Write-Host "Successfully uninstalled CTT PowerShell Profile." -ForegroundColor Green
@@ -3,7 +3,7 @@ title: "System Tray Battery Percentage"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1236} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1268}
"WPFToggleBatteryPercentage": { "WPFToggleBatteryPercentage": {
"Content": "System Tray Battery Percentage", "Content": "System Tray Battery Percentage",
"Description": "If enabled, Shows numeric battery percentage next to the battery icon in the system tray.", "Description": "If enabled, Shows numeric battery percentage next to the battery icon in the system tray.",
@@ -3,7 +3,7 @@ title: "Start Menu Bing Search"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1563} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1603}
"WPFToggleBingSearch": { "WPFToggleBingSearch": {
"Content": "Start Menu Bing Search", "Content": "Start Menu Bing Search",
"Description": "If enabled, Bing web search results will be included in your Start Menu search.", "Description": "If enabled, Bing web search results will be included in your Start Menu search.",
@@ -3,7 +3,7 @@ title: "Dark Theme for Windows"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1254} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1286}
"WPFToggleDarkMode": { "WPFToggleDarkMode": {
"Content": "Dark Theme for Windows", "Content": "Dark Theme for Windows",
"Description": "Enable/Disable Dark Mode.", "Description": "Enable/Disable Dark Mode.",
@@ -3,7 +3,7 @@ title: "BSoD Verbose Mode"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1210} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1242}
"WPFToggleDetailedBSoD": { "WPFToggleDetailedBSoD": {
"Content": "BSoD Verbose Mode", "Content": "BSoD Verbose Mode",
"Description": "If enabled, you will see a detailed Blue Screen of Death (BSOD) with more information.", "Description": "If enabled, you will see a detailed Blue Screen of Death (BSOD) with more information.",
@@ -3,7 +3,7 @@ title: "Cross-Device Resume"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1192} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1224}
"WPFToggleDisableCrossDeviceResume": { "WPFToggleDisableCrossDeviceResume": {
"Content": "Cross-Device Resume", "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.", "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.",
@@ -0,0 +1,37 @@
---
title: "Game Mode"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1765}
"WPFToggleGameMode": {
"Content": "Game Mode",
"Description": "If enabled, Windows prioritizes gaming performance by allocating system resources. Disable for audio/video production to prevent interference.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",
"registry": [
{
"Path": "HKCU:\\Software\\Microsoft\\GameBar",
"Name": "AllowAutoGameMode",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "true"
},
{
"Path": "HKCU:\\Software\\Microsoft\\GameBar",
"Name": "AutoGameModeEnabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "true"
}
],
```
## 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://www.wikiwand.com/en/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).
@@ -3,7 +3,7 @@ title: "File Explorer Hidden Files"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1324} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1356}
"WPFToggleHiddenFiles": { "WPFToggleHiddenFiles": {
"Content": "File Explorer Hidden Files", "Content": "File Explorer Hidden Files",
"Description": "If enabled, Hidden Files will be shown.", "Description": "If enabled, Hidden Files will be shown.",
@@ -3,7 +3,7 @@ title: "Settings Home Page"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1545} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1585}
"WPFToggleHideSettingsHome": { "WPFToggleHideSettingsHome": {
"Content": "Settings Home Page", "Content": "Settings Home Page",
"Description": "Enable or disable the Home Page in the Windows Settings app.", "Description": "Enable or disable the Home Page in the Windows Settings app.",
@@ -3,7 +3,7 @@ title: "Logon Screen Acrylic Blur"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1581} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1621}
"WPFToggleLoginBlur": { "WPFToggleLoginBlur": {
"Content": "Logon Screen Acrylic Blur", "Content": "Logon Screen Acrylic Blur",
"Description": "If disabled, the acrylic blur effect will be removed on the Windows 10/11 login screen background.", "Description": "If disabled, the acrylic blur effect will be removed on the Windows 10/11 login screen background.",
@@ -0,0 +1,29 @@
---
title: "Enable Long Paths"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1791}
"WPFToggleLongPaths": {
"Content": "Enable Long Paths",
"Description": "Enables support for file paths longer than 260 characters.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",
"registry": [
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem",
"Name": "LongPathsEnabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "false"
}
],
```
## 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://www.wikiwand.com/en/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).
@@ -3,7 +3,7 @@ title: "Mouse Acceleration"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1449} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1489}
"WPFToggleMouseAcceleration": { "WPFToggleMouseAcceleration": {
"Content": "Mouse Acceleration", "Content": "Mouse Acceleration",
"Description": "If enabled, the Cursor movement is affected by the speed of your physical mouse movements.", "Description": "If enabled, the Cursor movement is affected by the speed of your physical mouse movements.",
@@ -3,7 +3,7 @@ title: "Multiplane Overlay"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1431} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1463}
"WPFToggleMultiplaneOverlay": { "WPFToggleMultiplaneOverlay": {
"Content": "Multiplane Overlay", "Content": "Multiplane Overlay",
"Description": "Enable or disable the Multiplane Overlay, which can sometimes cause issues with graphics cards.", "Description": "Enable or disable the Multiplane Overlay, which can sometimes cause issues with graphics cards.",
@@ -18,6 +18,14 @@ description: ""
"Type": "DWord", "Type": "DWord",
"OriginalValue": "5", "OriginalValue": "5",
"DefaultState": "true" "DefaultState": "true"
},
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers",
"Name": "DisableOverlays",
"Value": "1",
"Type": "DWord",
"OriginalValue": "0",
"DefaultState": "false"
} }
], ],
``` ```
@@ -3,7 +3,7 @@ title: "Microsoft Outlook New Version"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1370} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1402}
"WPFToggleNewOutlook": { "WPFToggleNewOutlook": {
"Content": "Microsoft Outlook New Version", "Content": "Microsoft Outlook New Version",
"Description": "If disabled, it removes the new Outlook toggle, disables the new Outlook migration, and ensures the classic Outlook application is used.", "Description": "If disabled, it removes the new Outlook toggle, disables the new Outlook migration, and ensures the classic Outlook application is used.",
@@ -3,7 +3,7 @@ title: "Num Lock on Startup"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1483} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1523}
"WPFToggleNumLock": { "WPFToggleNumLock": {
"Content": "Num Lock on Startup", "Content": "Num Lock on Startup",
"Description": "Toggle the Num Lock key state when your computer starts.", "Description": "Toggle the Num Lock key state when your computer starts.",
@@ -3,7 +3,7 @@ title: "S3 Sleep"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1527} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1567}
"WPFToggleS3Sleep": { "WPFToggleS3Sleep": {
"Content": "S3 Sleep", "Content": "S3 Sleep",
"Description": "Toggles between Modern Standby and S3 Sleep.", "Description": "Toggles between Modern Standby and S3 Sleep.",
@@ -3,7 +3,7 @@ title: "File Explorer File Extensions"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1296} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1328}
"WPFToggleShowExt": { "WPFToggleShowExt": {
"Content": "File Explorer File Extensions", "Content": "File Explorer File Extensions",
"Description": "If enabled, File extensions (e.g., .txt, .jpg) are visible.", "Description": "If enabled, File extensions (e.g., .txt, .jpg) are visible.",
@@ -3,7 +3,7 @@ title: "S0 Sleep Network Connectivity"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1509} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1549}
"WPFToggleStandbyFix": { "WPFToggleStandbyFix": {
"Content": "S0 Sleep Network Connectivity", "Content": "S0 Sleep Network Connectivity",
"Description": "Enable or disable network connectivity during S0 Sleep.", "Description": "Enable or disable network connectivity during S0 Sleep.",
@@ -3,7 +3,7 @@ title: "Start Menu Recommendations"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1599} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1639}
"WPFToggleStartMenuRecommendations": { "WPFToggleStartMenuRecommendations": {
"Content": "Start Menu Recommendations", "Content": "Start Menu Recommendations",
"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.", "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.",
@@ -3,7 +3,7 @@ title: "Sticky Keys"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1643} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1683}
"WPFToggleStickyKeys": { "WPFToggleStickyKeys": {
"Content": "Sticky Keys", "Content": "Sticky Keys",
"Description": "If enabled, 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.", "Description": "If enabled, 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.",
@@ -3,7 +3,7 @@ title: "Taskbar Task View Icon"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1707} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1747}
"WPFToggleTaskView": { "WPFToggleTaskView": {
"Content": "Taskbar Task View Icon", "Content": "Taskbar Task View Icon",
"Description": "If enabled, Task View Button in Taskbar will be shown.", "Description": "If enabled, Task View Button in Taskbar will be shown.",
@@ -3,7 +3,7 @@ title: "Taskbar Centered Icons"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1661} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1701}
"WPFToggleTaskbarAlignment": { "WPFToggleTaskbarAlignment": {
"Content": "Taskbar Centered Icons", "Content": "Taskbar Centered Icons",
"Description": "[Windows 11] If enabled, the Taskbar Items will be shown on the Center, otherwise the Taskbar Items will be shown on the Left.", "Description": "[Windows 11] If enabled, the Taskbar Items will be shown on the Center, otherwise the Taskbar Items will be shown on the Left.",
@@ -3,7 +3,7 @@ title: "Taskbar Search Icon"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1689} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1729}
"WPFToggleTaskbarSearch": { "WPFToggleTaskbarSearch": {
"Content": "Taskbar Search Icon", "Content": "Taskbar Search Icon",
"Description": "If enabled, Search Button will be on the Taskbar.", "Description": "If enabled, Search Button will be on the Taskbar.",
@@ -3,7 +3,7 @@ title: "Logon Verbose Mode"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1352} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1384}
"WPFToggleVerboseLogon": { "WPFToggleVerboseLogon": {
"Content": "Logon Verbose Mode", "Content": "Logon Verbose Mode",
"Description": "Show detailed messages during the login process for troubleshooting and diagnostics.", "Description": "Show detailed messages during the login process for troubleshooting and diagnostics.",
@@ -3,7 +3,7 @@ title: "ConsumerFeatures - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=440} ```json {filename="config/tweaks.json",linenos=inline,linenostart=459}
"WPFTweaksConsumerFeatures": { "WPFTweaksConsumerFeatures": {
"Content": "ConsumerFeatures - Disable", "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 (eg. Phone Link).", "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 (eg. Phone Link).",
@@ -3,11 +3,11 @@ title: "Unwanted Pre-Installed Apps - Remove"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=802} ```json {filename="config/tweaks.json",linenos=inline,linenostart=821}
"WPFTweaksDeBloat": { "WPFTweaksDeBloat": {
"Content": "Unwanted Pre-Installed Apps - Remove", "Content": "Unwanted Pre-Installed Apps - Remove",
"Description": "This will remove a bunch of Windows pre-installed applications which most people dont want on there system.", "Description": "This will remove a bunch of Windows pre-installed applications which most people dont want on their system.",
"category": "z__Advanced Tweaks - CAUTION", "category": "Essential Tweaks",
"panel": "1", "panel": "1",
"appx": [ "appx": [
"Microsoft.WindowsFeedbackHub", "Microsoft.WindowsFeedbackHub",
@@ -3,7 +3,7 @@ title: "Temporary Files - Remove"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1087} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1119}
"WPFTweaksDeleteTempFiles": { "WPFTweaksDeleteTempFiles": {
"Content": "Temporary Files - Remove", "Content": "Temporary Files - Remove",
"Description": "Erases TEMP Folders.", "Description": "Erases TEMP Folders.",
@@ -0,0 +1,18 @@
---
title: "BitLocker - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=610}
"WPFTweaksDisableBitLocker": {
"Content": "BitLocker - Disable",
"Description": "Disables BitLocker.",
"category": "Essential Tweaks",
"panel": "1",
"InvokeScript": [
"Disable-BitLocker -MountPoint $Env:SystemDrive"
],
"UndoScript": [
"Enable-BitLocker -MountPoint $Env:SystemDrive"
],
```
@@ -3,7 +3,7 @@ title: "File Explorer Automatic Folder Discovery - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1756} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1840}
"WPFTweaksDisableExplorerAutoDiscovery": { "WPFTweaksDisableExplorerAutoDiscovery": {
"Content": "File Explorer Automatic Folder Discovery - Disable", "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.", "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: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1074} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1106}
"WPFTweaksDiskCleanup": { "WPFTweaksDiskCleanup": {
"Content": "Disk Cleanup - Run", "Content": "Disk Cleanup - Run",
"Description": "Runs Disk Cleanup on Drive C: and removes old Windows Updates.", "Description": "Runs Disk Cleanup on Drive C: and removes old Windows Updates.",
@@ -3,7 +3,7 @@ title: "End Task With Right Click - Enable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=870} ```json {filename="config/tweaks.json",linenos=inline,linenostart=889}
"WPFTweaksEndTaskOnTaskbar": { "WPFTweaksEndTaskOnTaskbar": {
"Content": "End Task With Right Click - Enable", "Content": "End Task With Right Click - Enable",
"Description": "Enables option to end task when right clicking a program in the taskbar.", "Description": "Enables option to end task when right clicking a program in the taskbar.",
@@ -3,7 +3,7 @@ title: "PowerShell 7 Telemetry - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=886} ```json {filename="config/tweaks.json",linenos=inline,linenostart=905}
"WPFTweaksPowershell7Tele": { "WPFTweaksPowershell7Tele": {
"Content": "PowerShell 7 Telemetry - Disable", "Content": "PowerShell 7 Telemetry - Disable",
"Description": "Creates an Environment Variable called 'POWERSHELL_TELEMETRY_OPTOUT' with a value of '1' which will tell PowerShell 7 to not send Telemetry Data.", "Description": "Creates an Environment Variable called 'POWERSHELL_TELEMETRY_OPTOUT' with a value of '1' which will tell PowerShell 7 to not send Telemetry Data.",
@@ -3,7 +3,7 @@ title: "Restore Point - Create"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=843} ```json {filename="config/tweaks.json",linenos=inline,linenostart=862}
"WPFTweaksRestorePoint": { "WPFTweaksRestorePoint": {
"Content": "Restore Point - Create", "Content": "Restore Point - Create",
"Description": "Creates a restore point at runtime in case a revert is needed from WinUtil modifications.", "Description": "Creates a restore point at runtime in case a revert is needed from WinUtil modifications.",
@@ -6,7 +6,7 @@ description: ""
```json {filename="config/tweaks.json",linenos=inline,linenostart=175} ```json {filename="config/tweaks.json",linenos=inline,linenostart=175}
"WPFTweaksServices": { "WPFTweaksServices": {
"Content": "Services - Set to Manual", "Content": "Services - Set to Manual",
"Description": "Turns a bunch of system services to manual that don't need to be running all the time. This is pretty harmless as if the service is needed, it will simply start on demand.", "Description": "Sets some services to Manual startup and adjusts the SvcHostSplitThresholdInKB registry value to better match system memory, which can significantly reduce the number of svchost.exe processes.",
"category": "Essential Tweaks", "category": "Essential Tweaks",
"panel": "1", "panel": "1",
"service": [ "service": [
@@ -25,16 +25,6 @@ description: ""
"StartupType": "Manual", "StartupType": "Manual",
"OriginalType": "Automatic" "OriginalType": "Automatic"
}, },
{
"Name": "RemoteAccess",
"StartupType": "Disabled",
"OriginalType": "Disabled"
},
{
"Name": "RemoteRegistry",
"StartupType": "Disabled",
"OriginalType": "Disabled"
},
{ {
"Name": "StorSvc", "Name": "StorSvc",
"StartupType": "Manual", "StartupType": "Manual",
@@ -44,26 +34,6 @@ description: ""
"Name": "SharedAccess", "Name": "SharedAccess",
"StartupType": "Disabled", "StartupType": "Disabled",
"OriginalType": "Automatic" "OriginalType": "Automatic"
},
{
"Name": "TermService",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "TroubleshootingSvc",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "seclogon",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "ssh-agent",
"StartupType": "Disabled",
"OriginalType": "Disabled"
} }
], ],
"InvokeScript": [ "InvokeScript": [
@@ -3,7 +3,7 @@ title: "Telemetry - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=456} ```json {filename="config/tweaks.json",linenos=inline,linenostart=475}
"WPFTweaksTelemetry": { "WPFTweaksTelemetry": {
"Content": "Telemetry - Disable", "Content": "Telemetry - Disable",
"Description": "Disables Microsoft Telemetry.", "Description": "Disables Microsoft Telemetry.",
@@ -3,7 +3,7 @@ title: "Windows Platform Binary Table (WPBT) - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=942} ```json {filename="config/tweaks.json",linenos=inline,linenostart=974}
"WPFTweaksWPBT": { "WPFTweaksWPBT": {
"Content": "Windows Platform Binary Table (WPBT) - Disable", "Content": "Windows Platform Binary Table (WPBT) - Disable",
"Description": "If enabled, WPBT allows your computer vendor to execute programs at boot time, such as anti-theft software, software drivers, as well as force install software without user consent. Poses potential security risk.", "Description": "If enabled, WPBT allows your computer vendor to execute programs at boot time, such as anti-theft software, software drivers, as well as force install software without user consent. Poses potential security risk.",
@@ -3,7 +3,7 @@ title: "Adobe URL Block List - Enable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1022} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1054}
"WPFTweaksBlockAdobeNet": { "WPFTweaksBlockAdobeNet": {
"Content": "Adobe URL Block List - Enable", "Content": "Adobe URL Block List - Enable",
"Description": "Reduces user interruptions by selectively blocking connections to Adobe's activation and telemetry servers. Credit: Ruddernation-Designs", "Description": "Reduces user interruptions by selectively blocking connections to Adobe's activation and telemetry servers. Credit: Ruddernation-Designs",
@@ -3,7 +3,7 @@ title: "Brave Browser - Debloat"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=245} ```json {filename="config/tweaks.json",linenos=inline,linenostart=215}
"WPFTweaksBraveDebloat": { "WPFTweaksBraveDebloat": {
"Content": "Brave Browser - Debloat", "Content": "Brave Browser - Debloat",
"Description": "Disables various annoyances like Brave Rewards, Leo AI, Crypto Wallet and VPN.", "Description": "Disables various annoyances like Brave Rewards, Leo AI, Crypto Wallet and VPN.",
@@ -44,6 +44,55 @@ description: ""
"Value": "0", "Value": "0",
"Type": "DWord", "Type": "DWord",
"OriginalValue": "<RemoveEntry>" "OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "BraveNewsDisabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "BraveTalkDisabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "TorDisabled",
"Value": "1",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "BraveP3AEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "UrlKeyedAnonymizedDataCollectionEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "SafeBrowsingExtendedReportingEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\BraveSoftware\\Brave",
"Name": "MetricsReportingEnabled",
"Value": "0",
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
} }
], ],
``` ```
@@ -3,7 +3,7 @@ title: "Background Apps - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1160} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1192}
"WPFTweaksDisableBGapps": { "WPFTweaksDisableBGapps": {
"Content": "Background Apps - Disable", "Content": "Background Apps - Disable",
"Description": "Disables all Microsoft Store apps from running in the background, which has to be done individually since Windows 11.", "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: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1176} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1208}
"WPFTweaksDisableFSO": { "WPFTweaksDisableFSO": {
"Content": "Fullscreen Optimizations - Disable", "Content": "Fullscreen Optimizations - Disable",
"Description": "Disables FSO in all applications. NOTE: This will disable Color Management in Exclusive Fullscreen.", "Description": "Disables FSO in all applications. NOTE: This will disable Color Management in Exclusive Fullscreen.",
@@ -3,7 +3,7 @@ title: "IPv6 - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1138} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1170}
"WPFTweaksDisableIPv6": { "WPFTweaksDisableIPv6": {
"Content": "IPv6 - Disable", "Content": "IPv6 - Disable",
"Description": "Disables IPv6.", "Description": "Disables IPv6.",
@@ -3,7 +3,7 @@ title: "System Tray Notifications & Calendar - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=999} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1031}
"WPFTweaksDisableNotifications": { "WPFTweaksDisableNotifications": {
"Content": "System Tray Notifications & Calendar - Disable", "Content": "System Tray Notifications & Calendar - Disable",
"Description": "Disables all Notifications INCLUDING Calendar.", "Description": "Disables all Notifications INCLUDING Calendar.",
@@ -3,7 +3,7 @@ title: "RDP Unsigned File Warnings - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=289} ```json {filename="config/tweaks.json",linenos=inline,linenostart=308}
"WPFTweaksDisableWarningForUnsignedRdp": { "WPFTweaksDisableWarningForUnsignedRdp": {
"Content": "RDP Unsigned File Warnings - Disable", "Content": "RDP Unsigned File Warnings - Disable",
"Description": "Disables warnings shown when launching unsigned RDP files introduced with the latest Windows 10 and 11 updates.", "Description": "Disables warnings shown when launching unsigned RDP files introduced with the latest Windows 10 and 11 updates.",
@@ -3,7 +3,7 @@ title: "Visual Effects - Set to Best Performance"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=680} ```json {filename="config/tweaks.json",linenos=inline,linenostart=699}
"WPFTweaksDisplay": { "WPFTweaksDisplay": {
"Content": "Visual Effects - Set to Best Performance", "Content": "Visual Effects - Set to Best Performance",
"Description": "Sets the system preferences to performance. You can do this manually with sysdm.cpl as well.", "Description": "Sets the system preferences to performance. You can do this manually with sysdm.cpl as well.",
@@ -3,7 +3,7 @@ title: "Microsoft Edge - Debloat"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=312} ```json {filename="config/tweaks.json",linenos=inline,linenostart=331}
"WPFTweaksEdgeDebloat": { "WPFTweaksEdgeDebloat": {
"Content": "Microsoft Edge - Debloat", "Content": "Microsoft Edge - Debloat",
"Description": "Disables various telemetry options, popups, and other annoyances in Edge.", "Description": "Disables various telemetry options, popups, and other annoyances in Edge.",
@@ -3,7 +3,7 @@ title: "IPv6 - Set IPv4 as Preferred"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1100} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1132}
"WPFTweaksIPv46": { "WPFTweaksIPv46": {
"Content": "IPv6 - Set IPv4 as Preferred", "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.", "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: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=958} ```json {filename="config/tweaks.json",linenos=inline,linenostart=990}
"WPFTweaksRazerBlock": { "WPFTweaksRazerBlock": {
"Content": "Razer Software Auto-Install - Disable", "Content": "Razer Software Auto-Install - Disable",
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software.", "Description": "Blocks ALL Razer Software installations. The hardware works fine without any software.",
@@ -1,32 +0,0 @@
---
title: "Microsoft Copilot - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=915}
"WPFTweaksRemoveCopilot": {
"Content": "Microsoft Copilot - Disable",
"Description": "Removes Copilot AppXPackages and related ai packages",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"InvokeScript": [
"
Get-AppxPackage -AllUsers *Copilot* | Remove-AppxPackage -AllUsers
Get-AppxPackage -AllUsers Microsoft.MicrosoftOfficeHub | Remove-AppxPackage -AllUsers
$Appx = (Get-AppxPackage MicrosoftWindows.Client.CoreAI).PackageFullName
$Sid = (Get-LocalUser $Env:UserName).Sid.Value
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx\\AppxAllUserStore\\EndOfLife\\$Sid\\$Appx\" -Force
Remove-AppxPackage $Appx
Write-Host \"Copilot Removed\"
"
],
"UndoScript": [
"
Write-Host \"Installing Copilot...\"
winget install --name Copilot --source msstore --accept-package-agreements --accept-source-agreements --silent
"
],
```
@@ -3,7 +3,7 @@ title: "Microsoft Edge - Remove"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=575} ```json {filename="config/tweaks.json",linenos=inline,linenostart=594}
"WPFTweaksRemoveEdge": { "WPFTweaksRemoveEdge": {
"Content": "Microsoft Edge - Remove", "Content": "Microsoft Edge - Remove",
"Description": "Unblocks Microsoft Edge uninstaller restrictions then uses that uninstaller to remove Microsoft Edge.", "Description": "Unblocks Microsoft Edge uninstaller restrictions then uses that uninstaller to remove Microsoft Edge.",
@@ -1,22 +0,0 @@
---
title: "File Explorer Gallery - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=663}
"WPFTweaksRemoveGallery": {
"Content": "File Explorer Gallery - Disable",
"Description": "Removes the Gallery from Explorer and sets This PC as default.",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"InvokeScript": [
"
Remove-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{e88865ea-0e1c-4e20-9aa6-edcd0212c87c}\"
"
],
"UndoScript": [
"
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{e88865ea-0e1c-4e20-9aa6-edcd0212c87c}\"
"
],
```
@@ -1,24 +1,34 @@
--- ---
title: "File Explorer Home - Disable" title: "File Explorer Home and Gallery - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=644} ```json {filename="config/tweaks.json",linenos=inline,linenostart=676}
"WPFTweaksRemoveHome": { "WPFTweaksRemoveHome": {
"Content": "File Explorer Home - Disable", "Content": "File Explorer Home and Gallery - Disable",
"Description": "Removes the Home from Explorer and sets This PC as default.", "Description": "Removes the Home and Gallery from Explorer and sets This PC as default.",
"category": "z__Advanced Tweaks - CAUTION", "category": "z__Advanced Tweaks - CAUTION",
"panel": "1", "panel": "1",
"InvokeScript": [ "registry": [
" {
Remove-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{f874310e-b6b7-47dc-bc84-b9e6b38f5903}\" "Path": "HKCU:\\Software\\Classes\\CLSID\\{f874310e-b6b7-47dc-bc84-b9e6b38f5903}",
Set-ItemProperty -Path \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\" -Name LaunchTo -Value 1 "Name": "System.IsPinnedToNameSpaceTree",
" "Value": "0",
], "Type": "DWord",
"UndoScript": [ "OriginalValue": "<RemoveEntry>"
" },
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{f874310e-b6b7-47dc-bc84-b9e6b38f5903}\" {
Set-ItemProperty -Path \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\" -Name LaunchTo -Value 0 "Path": "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
" "Name": "LaunchTo",
"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://www.wikiwand.com/en/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).
@@ -3,7 +3,7 @@ title: "Microsoft OneDrive - Remove"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=607} ```json {filename="config/tweaks.json",linenos=inline,linenostart=639}
"WPFTweaksRemoveOneDrive": { "WPFTweaksRemoveOneDrive": {
"Content": "Microsoft OneDrive - Remove", "Content": "Microsoft OneDrive - Remove",
"Description": "Denies permission to remove OneDrive user files, then uses its own uninstaller to remove it and restores the original permission afterward.", "Description": "Denies permission to remove OneDrive user files, then uses its own uninstaller to remove it and restores the original permission afterward.",
@@ -3,7 +3,7 @@ title: "Right-Click Menu Previous Layout - Enable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1052} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1084}
"WPFTweaksRightClickMenu": { "WPFTweaksRightClickMenu": {
"Content": "Right-Click Menu Previous Layout - Enable", "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.", "Description": "Restores the classic context menu when right-clicking in File Explorer, replacing the simplified Windows 11 version.",
@@ -3,7 +3,7 @@ title: "Storage Sense - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=899} ```json {filename="config/tweaks.json",linenos=inline,linenostart=918}
"WPFTweaksStorage": { "WPFTweaksStorage": {
"Content": "Storage Sense - Disable", "Content": "Storage Sense - Disable",
"Description": "Storage Sense deletes temp files automatically.", "Description": "Storage Sense deletes temp files automatically.",
@@ -3,7 +3,7 @@ title: "Teredo - Disable"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1116} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1148}
"WPFTweaksTeredo": { "WPFTweaksTeredo": {
"Content": "Teredo - Disable", "Content": "Teredo - Disable",
"Description": "Teredo network tunneling is an IPv6 feature that can cause additional latency, but may cause problems with some games.", "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: "Date & Time - Set Time to UTC"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=591} ```json {filename="config/tweaks.json",linenos=inline,linenostart=623}
"WPFTweaksUTC": { "WPFTweaksUTC": {
"Content": "Date & Time - Set Time to UTC", "Content": "Date & Time - Set Time to UTC",
"Description": "Essential for computers that are dual booting. Fixes the time sync with Linux systems.", "Description": "Essential for computers that are dual booting. Fixes the time sync with Linux systems.",
@@ -0,0 +1,51 @@
---
title: "Windows AI - Disable"
description: ""
---
```json {filename="config/tweaks.json",linenos=inline,linenostart=934}
"WPFTweaksWindowsAI": {
"Content": "Windows AI - Disable",
"Description": "Removes or disables all ai features and packages",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"registry": [
{
"Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
"Name": "SettingsPageVisibility",
"Value": "hide:aicomponents",
"Type": "String",
"OriginalValue": "<RemoveEntry>"
},
{
"Path": "HKLM:\\SOFTWARE\\Policies\\WindowsNotepad",
"Name": "DisableAIFeatures",
"Value": 1,
"Type": "DWord",
"OriginalValue": "<RemoveEntry>"
}
],
"InvokeScript": [
"
$Appx = (Get-AppxPackage MicrosoftWindows.Client.CoreAI).PackageFullName
$Sid = (Get-LocalUser $Env:UserName).Sid.Value
New-Item \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx\\AppxAllUserStore\\EndOfLife\\$Sid\\$Appx\" -Force
Get-AppxPackage -AllUsers *Copilot* | Remove-AppxPackage -AllUsers
Get-AppxPackage -AllUsers Microsoft.MicrosoftOfficeHub | Remove-AppxPackage -AllUsers
Remove-AppxPackage $Appx
Set-Service -Name WSAIFabricSvc -StartupType Disabled
Disable-WindowsOptionalFeature -FeatureName Recall -Online
Write-Host \"Windows AI Disabled\"
"
],
```
## 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://www.wikiwand.com/en/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).
@@ -3,7 +3,7 @@ title: "Xbox & Gaming Components - Remove"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=779} ```json {filename="config/tweaks.json",linenos=inline,linenostart=798}
"WPFTweaksXboxRemoval": { "WPFTweaksXboxRemoval": {
"Content": "Xbox & Gaming Components - Remove", "Content": "Xbox & Gaming Components - Remove",
"Description": "Removes Xbox services, the Xbox app, Game Bar, and related authentication components.", "Description": "Removes Xbox services, the Xbox app, Game Bar, and related authentication components.",
@@ -3,7 +3,7 @@ title: "DNS - Set to:"
description: "" description: ""
--- ---
```json {filename="config/tweaks.json",linenos=inline,linenostart=1732} ```json {filename="config/tweaks.json",linenos=inline,linenostart=1816}
"WPFchangedns": { "WPFchangedns": {
"Content": "DNS - Set to:", "Content": "DNS - Set to:",
"category": "z__Advanced Tweaks - CAUTION", "category": "z__Advanced Tweaks - CAUTION",
+1 -1
View File
@@ -16,7 +16,7 @@ To create a config file:
Once you have exported a config, launch Winutil with it using this command: Once you have exported a config, launch Winutil with it using this command:
```powershell ```powershell
& ([ScriptBlock]::Create((irm "https://christitus.com/win"))) -Config "C:\Path\To\Config.json" -Run & ([ScriptBlock]::Create((irm "https://christitus.com/win"))) -Config "C:\Path\To\Config.json"
``` ```
This is useful for: This is useful for:
+1 -1
View File
@@ -2,4 +2,4 @@ module github.com/ChrisTitusTech/WinUtil
go 1.26 go 1.26
require github.com/imfing/hextra v0.12.1 // indirect require github.com/imfing/hextra v0.12.3 // indirect
+2 -8
View File
@@ -1,8 +1,2 @@
github.com/imfing/hextra v0.9.7 h1:Zg5n24us36Bn/S/5mEUPkRW6uwE6vHHEqWSgN0bPXaM= github.com/imfing/hextra v0.12.3 h1:DZHY2rUWYteyzjlHi9r4n7Bb5e2Q+6LXe4C1Dqn0ZjM=
github.com/imfing/hextra v0.9.7/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI= github.com/imfing/hextra v0.12.3/go.mod h1:vi+yhpq8YPp/aghvJlNKVnJKcPJ/VyAEcfC1BSV9ARo=
github.com/imfing/hextra v0.11.1 h1:8pTc4ReYbzGTHAnyiebmlT3ijFfIXiGu1r7tM/UGjFI=
github.com/imfing/hextra v0.11.1/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI=
github.com/imfing/hextra v0.12.0 h1:f6y35hW/WDJEcx9S0dOmbICOBxYE0PmP6IJFsTUgVyY=
github.com/imfing/hextra v0.12.0/go.mod h1:YAv8XRNSmcqjieFwI7fVQK1AoY2Do+45DO9HGqxSGu4=
github.com/imfing/hextra v0.12.1 h1:3t1n0bmJbDzSTVfht93UDcfF1BXMRjeFojA071ri2l8=
github.com/imfing/hextra v0.12.1/go.mod h1:vi+yhpq8YPp/aghvJlNKVnJKcPJ/VyAEcfC1BSV9ARo=
@@ -3,78 +3,134 @@ function Find-AppsByNameOrDescription {
.SYNOPSIS .SYNOPSIS
Searches through the Apps on the Install Tab and hides all entries that do not match the string Searches through the Apps on the Install Tab and hides all entries that do not match the string
.DESCRIPTION
Filters application entries by name or description using literal string matching.
Respects collapsed category state and handles null $sync gracefully.
.PARAMETER SearchString .PARAMETER SearchString
The string to be searched for The string to be searched for. Wildcards are treated as literal characters.
.NOTES
- Uses module-scope $sync (no parameter needed; inherits from caller's scope)
- Performs literal matching (no wildcard expansion)
- Safely handles missing hashtable keys and null UI elements
- Protected by try/catch to prevent UI thread crashes
#> #>
param( param(
[Parameter(Mandatory=$false)] [Parameter(Mandatory = $false)]
[string]$SearchString = "" [string]$SearchString = ""
) )
# Reset the visibility if the search string is empty or the search is cleared
if ([string]::IsNullOrWhiteSpace($SearchString)) {
$sync.ItemsControl.Items | ForEach-Object {
# Each item is a StackPanel container
$_.Visibility = [Windows.Visibility]::Visible
# Validate that $sync exists and has required structure
if ($null -eq $sync) {
Write-Warning "Find-AppsByNameOrDescription: Global `$sync not found. Aborting search."
return
}
if ($null -eq $sync.ItemsControl) {
Write-Warning "Find-AppsByNameOrDescription: `$sync.ItemsControl not initialized. Aborting search."
return
}
if ($null -eq $sync.configs -or $null -eq $sync.configs.applicationsHashtable) {
Write-Warning "Find-AppsByNameOrDescription: `$sync.configs.applicationsHashtable not initialized. Aborting search."
return
}
try {
# Reset the visibility if the search string is empty or the search is cleared
if ([string]::IsNullOrWhiteSpace($SearchString)) {
$sync.ItemsControl.Items | ForEach-Object {
# Each item is a StackPanel container
$_.Visibility = [Windows.Visibility]::Visible
if ($_.Children.Count -ge 2) {
$categoryLabel = $_.Children[0]
$wrapPanel = $_.Children[1]
# Keep category label visible
$categoryLabel.Visibility = [Windows.Visibility]::Visible
# Respect the collapsed state of categories (indicated by + prefix)
if ($categoryLabel.Content -like "+*") {
$wrapPanel.Visibility = [Windows.Visibility]::Collapsed
}
else {
$wrapPanel.Visibility = [Windows.Visibility]::Visible
}
# Show all apps within the category
$wrapPanel.Children | ForEach-Object {
$_.Visibility = [Windows.Visibility]::Visible
}
}
}
return
}
# Escape wildcard characters for literal matching
$escapedSearchString = [System.Management.Automation.WildcardPattern]::Escape($SearchString)
# Perform search
$sync.ItemsControl.Items | ForEach-Object {
# Each item is a StackPanel container with Children[0] = label, Children[1] = WrapPanel
if ($_.Children.Count -ge 2) { if ($_.Children.Count -ge 2) {
$categoryLabel = $_.Children[0] $categoryLabel = $_.Children[0]
$wrapPanel = $_.Children[1] $wrapPanel = $_.Children[1]
$categoryHasMatch = $false
# Keep category label visible # Keep category label visible
$categoryLabel.Visibility = [Windows.Visibility]::Visible $categoryLabel.Visibility = [Windows.Visibility]::Visible
# Respect the collapsed state of categories (indicated by + prefix) # Search through apps in this category
if ($categoryLabel.Content -like "+*") {
$wrapPanel.Visibility = [Windows.Visibility]::Collapsed
} else {
$wrapPanel.Visibility = [Windows.Visibility]::Visible
}
# Show all apps within the category
$wrapPanel.Children | ForEach-Object { $wrapPanel.Children | ForEach-Object {
$_.Visibility = [Windows.Visibility]::Visible # Safely retrieve app entry from hashtable
$appTag = $_.Tag
$appEntry = $null
if (-not [string]::IsNullOrWhiteSpace($appTag) -and $sync.configs.applicationsHashtable.ContainsKey($appTag)) {
$appEntry = $sync.configs.applicationsHashtable[$appTag]
}
# Check if app matches search criteria
if ($null -ne $appEntry) {
$contentMatch = $appEntry.Content -like "*$escapedSearchString*"
$descriptionMatch = $appEntry.Description -like "*$escapedSearchString*"
if ($contentMatch -or $descriptionMatch) {
# Show the App and mark that this category has a match
$_.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
}
else {
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
else {
# Hide app if no entry found (data integrity issue)
$_.Visibility = [Windows.Visibility]::Collapsed
}
} }
}
}
return
}
# Perform search # If category has matches, show the WrapPanel and update the category label to expanded state
$sync.ItemsControl.Items | ForEach-Object { if ($categoryHasMatch) {
# Each item is a StackPanel container with Children[0] = label, Children[1] = WrapPanel $wrapPanel.Visibility = [Windows.Visibility]::Visible
if ($_.Children.Count -ge 2) {
$categoryLabel = $_.Children[0]
$wrapPanel = $_.Children[1]
$categoryHasMatch = $false
# Keep category label visible
$categoryLabel.Visibility = [Windows.Visibility]::Visible
# Search through apps in this category
$wrapPanel.Children | ForEach-Object {
$appEntry = $sync.configs.applicationsHashtable.$($_.Tag)
if ($appEntry.Content -like "*$SearchString*" -or $appEntry.Description -like "*$SearchString*") {
# Show the App and mark that this category has a match
$_.Visibility = [Windows.Visibility]::Visible $_.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true # Update category label to show expanded state (-)
if ($categoryLabel.Content -like "+*") {
$categoryLabel.Content = $categoryLabel.Content -replace "^\+ ", "- "
}
} }
else { else {
# Hide the entire category container if no matches
$_.Visibility = [Windows.Visibility]::Collapsed $_.Visibility = [Windows.Visibility]::Collapsed
} }
} }
# If category has matches, show the WrapPanel and update the category label to expanded state
if ($categoryHasMatch) {
$wrapPanel.Visibility = [Windows.Visibility]::Visible
$_.Visibility = [Windows.Visibility]::Visible
# Update category label to show expanded state (-)
if ($categoryLabel.Content -like "+*") {
$categoryLabel.Content = $categoryLabel.Content -replace "^\+ ", "- "
}
} else {
# Hide the entire category container if no matches
$_.Visibility = [Windows.Visibility]::Collapsed
}
} }
} }
catch {
Write-Warning "Find-AppsByNameOrDescription: An error occurred during search: $_"
# Fail gracefully - do not crash the UI thread
return
}
} }
@@ -3,98 +3,300 @@ function Find-TweaksByNameOrDescription {
.SYNOPSIS .SYNOPSIS
Searches through the Tweaks on the Tweaks Tab and hides all entries that do not match the search string Searches through the Tweaks on the Tweaks Tab and hides all entries that do not match the search string
.DESCRIPTION
Filters tweak entries by name or description using literal string matching (no wildcard expansion).
Respects collapsed category state and handles null $sync gracefully.
Safe for rapid keystroke events; no terminal spam on error conditions.
.PARAMETER SearchString .PARAMETER SearchString
The string to be searched for The string to be searched for. Wildcards are treated as literal characters.
.NOTES
- Uses module-scope $sync (resolved via global/script fallback if needed)
- Performs literal matching (no wildcard expansion)
- Safely handles missing UI elements and null properties
- Protected by try/catch to prevent UI thread crashes
- PowerShell 5.1 compatible (no ternary operators, no advanced language features)
#> #>
param( param(
[Parameter(Mandatory=$false)] [Parameter(Mandatory = $false)]
[string]$SearchString = "" [string]$SearchString = ""
) )
# Reset the visibility if the search string is empty or the search is cleared # ──────────────────────────────────────────────────────────────────────────────
if ([string]::IsNullOrWhiteSpace($SearchString)) { # 1. RESOLVE $SYNC WITH MULTI-LEVEL FALLBACK
# Show all categories # ──────────────────────────────────────────────────────────────────────────────
$tweakspanel = $sync.Form.FindName("tweakspanel")
$tweakspanel.Children | ForEach-Object {
$_.Visibility = [Windows.Visibility]::Visible
# Foreach category section, show all items if ($null -eq $Sync) {
if ($_ -is [Windows.Controls.Border]) { $Sync = $global:sync
$_.Visibility = [Windows.Visibility]::Visible if ($null -eq $Sync) {
$Sync = $script:sync
# Find ItemsControl
$dockPanel = $_.Child
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
if ($itemsControl) {
# Show items in the category
foreach ($item in $itemsControl.Items) {
if ($item -is [Windows.Controls.Label]) {
$item.Visibility = [Windows.Visibility]::Visible
} elseif ($item -is [Windows.Controls.DockPanel] -or
$item -is [Windows.Controls.StackPanel]) {
$item.Visibility = [Windows.Visibility]::Visible
}
}
}
}
}
} }
}
# Validate that $Sync exists and has required structure
if ($null -eq $Sync) {
# Silent return - function called on every keystroke; no warning spam
return return
} }
# Search for matching tweaks when search string is not null if ($null -eq $Sync.Form) {
$tweakspanel = $sync.Form.FindName("tweakspanel") # Silent return - form not yet initialized
return
}
$tweakspanel.Children | ForEach-Object { # ──────────────────────────────────────────────────────────────────────────────
$categoryBorder = $_ # 2. GET REFERENCE TO TWEAKS PANEL
$categoryVisible = $false # ──────────────────────────────────────────────────────────────────────────────
if ($_ -is [Windows.Controls.Border]) { $tweaksPanel = $null
# Find the ItemsControl try {
$dockPanel = $_.Child $tweaksPanel = $Sync.Form.FindName("tweakspanel")
if ($dockPanel -is [Windows.Controls.DockPanel]) { }
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } catch {
if ($itemsControl) { # Silent return - panel not found or disposed
$categoryLabel = $null return
}
# Process all items in the ItemsControl if ($null -eq $tweaksPanel) {
for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) { # Silent return - panel doesn't exist
$item = $itemsControl.Items[$i] return
}
if ($item -is [Windows.Controls.Label]) { # ──────────────────────────────────────────────────────────────────────────────
$categoryLabel = $item # 3. HANDLE EMPTY/WHITESPACE SEARCH STRING - RESET TO DEFAULT STATE
$item.Visibility = [Windows.Visibility]::Collapsed # ──────────────────────────────────────────────────────────────────────────────
} elseif ($item -is [Windows.Controls.DockPanel]) {
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
if ($label -and ($label.Content -like "*$SearchString*" -or $label.ToolTip -like "*$SearchString*")) { if ([string]::IsNullOrWhiteSpace($SearchString)) {
$item.Visibility = [Windows.Visibility]::Visible try {
if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible } $tweaksPanel.Children | ForEach-Object {
$categoryVisible = $true $categoryBorder = $_
} else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
} elseif ($item -is [Windows.Controls.StackPanel]) {
# StackPanel which contain checkboxes or other elements
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
if ($checkbox -and ($checkbox.Content -like "*$SearchString*" -or $checkbox.ToolTip -like "*$SearchString*")) { # Safely set visibility
$item.Visibility = [Windows.Visibility]::Visible if ($null -ne $categoryBorder) {
if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible } $categoryBorder.Visibility = [Windows.Visibility]::Visible
$categoryVisible = $true }
} else {
$item.Visibility = [Windows.Visibility]::Collapsed # Process each category
if ($categoryBorder -is [Windows.Controls.Border]) {
$dockPanel = $null
if ($null -ne $categoryBorder.Child) {
$dockPanel = $categoryBorder.Child
}
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
if ($null -ne $itemsControl) {
# Show all items in the category
foreach ($item in $itemsControl.Items) {
if ($null -ne $item) {
# Check if it's a category label (first Label in the ItemsControl)
if ($item -is [Windows.Controls.Label]) {
$item.Visibility = [Windows.Visibility]::Visible
}
elseif ($item -is [Windows.Controls.DockPanel] -or $item -is [Windows.Controls.StackPanel]) {
# Show all checkbox containers
$item.Visibility = [Windows.Visibility]::Visible
}
}
} }
} }
} }
} }
} }
}
catch {
# Silent catch - UI element may be disposed
}
# Set the visibility based on if any item matched return
$categoryBorder.Visibility = if ($categoryVisible) { [Windows.Visibility]::Visible } else { [Windows.Visibility]::Collapsed } }
# ──────────────────────────────────────────────────────────────────────────────
# 4. PERFORM LITERAL SEARCH (NO WILDCARD EXPANSION)
# ──────────────────────────────────────────────────────────────────────────────
try {
# Normalize search term once for the entire operation
$searchTerm = $SearchString
if ($null -eq $searchTerm) {
$searchTerm = ""
}
# Iterate through all categories
$tweaksPanel.Children | ForEach-Object {
$categoryBorder = $_
$categoryHasMatch = $false
if ($categoryBorder -is [Windows.Controls.Border]) {
$dockPanel = $null
if ($null -ne $categoryBorder.Child) {
$dockPanel = $categoryBorder.Child
}
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
if ($null -ne $itemsControl) {
$categoryLabel = $null
# Process all items (checkboxes, labels, panels) in the ItemsControl
for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) {
$item = $itemsControl.Items[$i]
if ($null -eq $item) {
continue
}
# ────────────────────────────────────────────────────────────
# Check if this is a category label (usually first Label)
# ────────────────────────────────────────────────────────────
if ($item -is [Windows.Controls.Label]) {
$categoryLabel = $item
# Initially hide category label; show it only if matches found
$item.Visibility = [Windows.Visibility]::Collapsed
}
# ────────────────────────────────────────────────────────────
# Check if this is a DockPanel containing a tweak checkbox
# ────────────────────────────────────────────────────────────
elseif ($item -is [Windows.Controls.DockPanel]) {
$checkbox = $null
$label = $null
# Safely extract checkbox and label
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
# Check if tweak matches search criteria
$itemMatches = $false
if ($null -ne $label) {
$labelContent = $label.Content
$labelToolTip = $label.ToolTip
# Safely null-check properties
if ($null -eq $labelContent) {
$labelContent = ""
}
if ($null -eq $labelToolTip) {
$labelToolTip = ""
}
# Convert to string and perform LITERAL matching
$labelContentStr = [string]$labelContent
$labelToolTipStr = [string]$labelToolTip
# Use IndexOf for literal matching (no wildcard interpretation)
$contentMatch = $labelContentStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
$toolTipMatch = $labelToolTipStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
if ($contentMatch -or $toolTipMatch) {
$itemMatches = $true
}
}
# Set visibility based on match result
if ($itemMatches) {
$item.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
}
else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
}
# ────────────────────────────────────────────────────────────
# Check if this is a StackPanel containing a tweak checkbox
# ────────────────────────────────────────────────────────────
elseif ($item -is [Windows.Controls.StackPanel]) {
$checkbox = $null
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$itemMatches = $false
if ($null -ne $checkbox) {
$checkboxContent = $checkbox.Content
$checkboxToolTip = $checkbox.ToolTip
# Safely null-check properties
if ($null -eq $checkboxContent) {
$checkboxContent = ""
}
if ($null -eq $checkboxToolTip) {
$checkboxToolTip = ""
}
# Convert to string and perform LITERAL matching
$checkboxContentStr = [string]$checkboxContent
$checkboxToolTipStr = [string]$checkboxToolTip
# Use IndexOf for literal matching (no wildcard interpretation)
$contentMatch = $checkboxContentStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
$toolTipMatch = $checkboxToolTipStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
if ($contentMatch -or $toolTipMatch) {
$itemMatches = $true
}
}
# Set visibility based on match result
if ($itemMatches) {
$item.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
}
else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
}
}
# ────────────────────────────────────────────────────────────
# Update category label visibility and expanded/collapsed state
# ────────────────────────────────────────────────────────────
if ($categoryHasMatch) {
# Show category label
if ($null -ne $categoryLabel) {
$categoryLabel.Visibility = [Windows.Visibility]::Visible
# Update category label to expanded state (change "+" to "-")
$labelContent = $categoryLabel.Content
if ($null -ne $labelContent) {
$labelStr = [string]$labelContent
# Safe string replacement without -replace regex
if ($labelStr.StartsWith("+ ")) {
$expandedLabel = "- " + $labelStr.Substring(2)
$categoryLabel.Content = $expandedLabel
}
}
}
}
}
}
# ────────────────────────────────────────────────────────────────
# Set category border visibility based on whether it has matches
# ────────────────────────────────────────────────────────────────
if ($categoryHasMatch) {
$categoryBorder.Visibility = [Windows.Visibility]::Visible
}
else {
$categoryBorder.Visibility = [Windows.Visibility]::Collapsed
}
}
} }
} }
catch {
# Silent catch - UI elements may be disposed or in unexpected state
# Do not log to terminal as this function is called on every keystroke
}
} }
-34
View File
@@ -1,34 +0,0 @@
function Get-LocalizedYesNo {
<#
.SYNOPSIS
This function runs choice.exe and captures its output to extract yes no in a localized Windows
.DESCRIPTION
The function retrieves the output of the command 'cmd /c "choice <nul 2>nul"' and converts the default output for Yes and No
in the localized format, such as "Yes=<first character>, No=<second character>".
.EXAMPLE
$yesNoArray = Get-LocalizedYesNo
Write-Host "Yes=$($yesNoArray[0]), No=$($yesNoArray[1])"
#>
# Run choice and capture its options as output
# The output shows the options for Yes and No as "[Y,N]?" in the (partially) localized format.
# eg. English: [Y,N]?
# Dutch: [Y,N]?
# German: [J,N]?
# French: [O,N]?
# Spanish: [S,N]?
# Italian: [S,N]?
# Russian: [Y,N]?
$line = cmd /c "choice <nul 2>nul"
$charactersArray = @()
$regexPattern = '([a-zA-Z])'
$charactersArray = [regex]::Matches($line, $regexPattern) | ForEach-Object { $_.Groups[1].Value }
Write-Debug "According to takeown.exe local Yes is $charactersArray[0]"
# Return the array of characters
return $charactersArray
}
-31
View File
@@ -1,31 +0,0 @@
function Get-WPFObjectName {
<#
.SYNOPSIS
This is a helper function that generates an objectname with the prefix WPF that can be used as a Powershell Variable after compilation.
To achieve this, all characters that are not a-z, A-Z or 0-9 are simply removed from the name.
.PARAMETER type
The type of object for which the name should be generated. (e.g. Label, Button, CheckBox...)
.PARAMETER name
The name or description to be used for the object. (invalid characters are removed)
.OUTPUTS
A string that can be used as a object/variable name in powershell.
For example: WPFLabelMicrosoftTools
.EXAMPLE
Get-WPFObjectName -type Label -name "Microsoft Tools"
#>
param(
[Parameter(Mandatory, position=0)]
[string]$type,
[Parameter(position=1)]
[string]$name
)
$Output = $("WPF"+$type+$name) -replace '[^a-zA-Z0-9]', ''
return $Output
}
@@ -1,24 +0,0 @@
function Get-WinUtilInstallerProcess {
<#
.SYNOPSIS
Checks if the given process is running
.PARAMETER Process
The process to check
.OUTPUTS
Boolean - True if the process is running
#>
param($Process)
if ($Null -eq $Process) {
return $false
}
if (Get-Process -Id $Process.Id -ErrorAction SilentlyContinue) {
return $true
}
return $false
}
@@ -1,18 +1,12 @@
function Get-WinUtilSelectedPackages function Get-WinUtilSelectedPackages {
{
<#
.SYNOPSIS
Sorts given packages based on installer preference and availability.
.OUTPUTS param(
Hashtable. Key = Package Manager, Value = ArrayList of packages to install [Parameter(Mandatory = $true)]
#> [object] $PackageList,
param (
[Parameter(Mandatory=$true)] [Parameter(Mandatory = $true)]
$PackageList, [PackageManagers] $Preference
[Parameter(Mandatory=$true)] )
[PackageManagers]$Preference
)
if ($PackageList.count -eq 1) { if ($PackageList.count -eq 1) {
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" } Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }
@@ -23,34 +17,21 @@ function Get-WinUtilSelectedPackages
$packages = [System.Collections.Hashtable]::new() $packages = [System.Collections.Hashtable]::new()
$packagesWinget = [System.Collections.ArrayList]::new() $packagesWinget = [System.Collections.ArrayList]::new()
$packagesChoco = [System.Collections.ArrayList]::new() $packagesChoco = [System.Collections.ArrayList]::new()
$packages[[PackageManagers]::Winget] = $packagesWinget $packages[[PackageManagers]::Winget] = $packagesWinget
$packages[[PackageManagers]::Choco] = $packagesChoco $packages[[PackageManagers]::Choco] = $packagesChoco
Write-Debug "Checking packages using Preference '$($Preference)'"
foreach ($package in $PackageList) { foreach ($package in $PackageList) {
switch ($Preference) { switch ($Preference) {
"Choco" { "Choco" {
if ($package.choco -eq "na") { if ($package.choco -eq "na") {
Write-Debug "$($package.content) has no Choco value." $null = $packagesWinget.add($package.winget)
$null = $packagesWinget.add($($package.winget))
Write-Host "Queueing $($package.winget) for WinGet..."
} else { } else {
$null = $packagesChoco.add($package.choco) $null = $packagesChoco.add($package.choco)
Write-Host "Queueing $($package.choco) for Chocolatey..."
} }
break
} }
"Winget" { "Winget" {
if ($package.winget -eq "na") { $null = $packagesWinget.add($package.winget)
Write-Debug "$($package.content) has no WinGet value."
$null = $packagesChoco.add($package.choco)
Write-Host "Queueing $($package.choco) for Chocolatey..."
} else {
$null = $packagesWinget.add($($package.winget))
Write-Host "Queueing $($package.winget) for WinGet..."
}
break
} }
} }
} }
+30 -61
View File
@@ -1,78 +1,47 @@
Function Get-WinUtilToggleStatus { Function Get-WinUtilToggleStatus {
<# param(
[string]$ToggleSwitch
)
.SYNOPSIS $toggleSwitchReg = if ($ToggleSwitch) {
Pulls the registry keys for the given toggle switch and checks whether the toggle should be checked or unchecked $sync.configs.tweaks.$ToggleSwitch.registry
} else {
$ToggleSwitchReg
}
.PARAMETER ToggleSwitch if (-not $toggleSwitchReg) {
The name of the toggle to check
.OUTPUTS
Boolean to set the toggle's status to
#>
Param($ToggleSwitch)
$ToggleSwitchReg = $sync.configs.tweaks.$ToggleSwitch.registry
try {
if (($ToggleSwitchReg.path -imatch "hku") -and !(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)
if (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue) {
Write-Debug "HKU drive created successfully."
} else {
Write-Debug "Failed to create HKU drive."
}
}
} catch {
Write-Error "An error occurred regarding the HKU Drive: $_"
return $false return $false
} }
if ($ToggleSwitchReg) { New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS
$count = 0
foreach ($regentry in $ToggleSwitchReg) { foreach ($regentry in $toggleSwitchReg) {
try {
if (!(Test-Path $regentry.Path)) { if (-not (Test-Path $regentry.Path)) {
New-Item -Path $regentry.Path -Force | Out-Null New-Item -Path $regentry.Path -Force | Out-Null
}
$regstate = (Get-ItemProperty -Path $regentry.Path).$($regentry.Name)
if ($null -eq $regstate) {
switch ($regentry.DefaultState) {
"true" {
$regstate = $regentry.Value
} }
$regstate = (Get-ItemProperty -path $regentry.Path).$($regentry.Name) "false" {
if ($regstate -eq $regentry.Value) { $regstate = $regentry.OriginalValue
$count += 1
Write-Debug "$($regentry.Name) is true (state: $regstate, value: $($regentry.Value), original: $($regentry.OriginalValue))"
} else {
Write-Debug "$($regentry.Name) is false (state: $regstate, value: $($regentry.Value), original: $($regentry.OriginalValue))"
} }
if ($null -eq $regstate) { default {
switch ($regentry.DefaultState) { Write-Error "Entry $($regentry.Name): missing value and no DefaultState"
"true" { $regstate = $regentry.OriginalValue
$regstate = $regentry.Value
$count += 1
}
"false" {
$regstate = $regentry.OriginalValue
}
default {
Write-Error "Entry for $($regentry.Name) does not exist and no DefaultState is defined."
$regstate = $regentry.OriginalValue
}
}
} }
} catch {
Write-Error "An unexpected error occurred: $_"
} }
} }
if ($count -eq $ToggleSwitchReg.Count) { if ($regstate -ne $regentry.Value) {
Write-Debug "$($ToggleSwitchReg.Name) is true (count: $count)"
return $true
} else {
Write-Debug "$($ToggleSwitchReg.Name) is false (count: $count)"
return $false return $false
} }
} else {
return $false
} }
return $true
} }
+10 -252
View File
@@ -1,258 +1,16 @@
function Install-WinUtilProgramChoco { function Install-WinUtilProgramChoco {
<# param (
.SYNOPSIS [Parameter(Mandatory=$true)]
Manages the installation or uninstallation of a list of Chocolatey packages. [ValidateSet("Install", "Uninstall")]
[string]$Action,
.PARAMETER Programs [Parameter(Mandatory=$true)]
A string array containing the programs to be installed or uninstalled. [string[]]$Programs
.PARAMETER Action
Specifies the action to perform: "Install" or "Uninstall". The default value is "Install".
.DESCRIPTION
This function processes a list of programs to be managed using Chocolatey. Depending on the specified action, it either installs or uninstalls each program in the list, updating the taskbar progress accordingly. After all operations are completed, temporary output files are cleaned up.
.EXAMPLE
Install-WinUtilProgramChoco -Programs @("7zip","chrome") -Action "Uninstall"
#>
param(
[Parameter(Mandatory, Position = 0)]
[string[]]$Programs,
[Parameter(Position = 1)]
[String]$Action = "Install"
) )
function Initialize-OutputFile { if ($Action -eq 'Install') {
<# Start-Process -FilePath choco -ArgumentList "install $Programs -y" -NoNewWindow -Wait
.SYNOPSIS } else {
Initializes an output file by removing any existing file and creating a new, empty file at the specified path. Start-Process -FilePath choco -ArgumentList "uninstall $Programs -y" -NoNewWindow -Wait
.PARAMETER filePath
The full path to the file to be initialized.
.DESCRIPTION
This function ensures that the specified file is reset by removing any existing file at the provided path and then creating a new, empty file. It is useful when preparing a log or output file for subsequent operations.
.EXAMPLE
Initialize-OutputFile -filePath "C:\temp\output.txt"
#>
param ($filePath)
Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue
New-Item -ItemType File -Path $filePath | Out-Null
}
function Invoke-ChocoCommand {
<#
.SYNOPSIS
Executes a Chocolatey command with the specified arguments and returns the exit code.
.PARAMETER arguments
The arguments to be passed to the Chocolatey command.
.DESCRIPTION
This function runs a specified Chocolatey command by passing the provided arguments to the `choco` executable. It waits for the process to complete and then returns the exit code, allowing the caller to determine success or failure based on the exit code.
.RETURNS
[int]
The exit code of the Chocolatey command.
.EXAMPLE
$exitCode = Invoke-ChocoCommand -arguments "install 7zip -y"
#>
param ($arguments)
return (Start-Process -FilePath "choco" -ArgumentList $arguments -Wait -PassThru).ExitCode
}
function Test-UpgradeNeeded {
<#
.SYNOPSIS
Checks if an upgrade is needed for a Chocolatey package based on the content of a log file.
.PARAMETER filePath
The path to the log file that contains the output of a Chocolatey install command.
.DESCRIPTION
This function reads the specified log file and checks for keywords that indicate whether an upgrade is needed. It returns a boolean value indicating whether the terms "reinstall" or "already installed" are present, which suggests that the package might need an upgrade.
.RETURNS
[bool]
True if the log file indicates that an upgrade is needed; otherwise, false.
.EXAMPLE
$isUpgradeNeeded = Test-UpgradeNeeded -filePath "C:\temp\install-output.txt"
#>
param ($filePath)
return Get-Content -Path $filePath | Select-String -Pattern "reinstall|already installed" -Quiet
}
function Update-TaskbarProgress {
<#
.SYNOPSIS
Updates the taskbar progress based on the current installation progress.
.PARAMETER currentIndex
The current index of the program being installed or uninstalled.
.PARAMETER totalPrograms
The total number of programs to be installed or uninstalled.
.DESCRIPTION
This function calculates the progress of the installation or uninstallation process and updates the taskbar accordingly. The taskbar is set to "Normal" if all programs have been processed, otherwise, it is set to "Error" as a placeholder.
.EXAMPLE
Update-TaskbarProgress -currentIndex 3 -totalPrograms 10
#>
param (
[int]$currentIndex,
[int]$totalPrograms
)
$progressState = if ($currentIndex -eq $totalPrograms) { "Normal" } else { "Error" }
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) }
}
function Install-ChocoPackage {
<#
.SYNOPSIS
Installs a Chocolatey package and optionally upgrades it if needed.
.PARAMETER Program
A string containing the name of the Chocolatey package to be installed.
.PARAMETER currentIndex
The current index of the program in the list of programs to be managed.
.PARAMETER totalPrograms
The total number of programs to be installed.
.DESCRIPTION
This function installs a Chocolatey package by running the `choco install` command. If the installation output indicates that an upgrade might be needed, the function will attempt to upgrade the package. The taskbar progress is updated after each package is processed.
.EXAMPLE
Install-ChocoPackage -Program $Program -currentIndex 0 -totalPrograms 5
#>
param (
[string]$Program,
[int]$currentIndex,
[int]$totalPrograms
)
$installOutputFile = "$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt"
Initialize-OutputFile $installOutputFile
Write-Host "Starting installation of $Program with Chocolatey."
try {
$installStatusCode = Invoke-ChocoCommand "install $Program -y --log-file $installOutputFile"
if ($installStatusCode -eq 0) {
if (Test-UpgradeNeeded $installOutputFile) {
$upgradeStatusCode = Invoke-ChocoCommand "upgrade $Program -y"
Write-Host "$Program was" $(if ($upgradeStatusCode -eq 0) { "upgraded successfully." } else { "not upgraded." })
}
else {
Write-Host "$Program installed successfully."
}
}
else {
Write-Host "Failed to install $Program."
}
}
catch {
Write-Host "Failed to install $Program due to an error: $_"
}
finally {
Update-TaskbarProgress $currentIndex $totalPrograms
}
}
function Uninstall-ChocoPackage {
<#
.SYNOPSIS
Uninstalls a Chocolatey package and any related metapackages.
.PARAMETER Program
A string containing the name of the Chocolatey package to be uninstalled.
.PARAMETER currentIndex
The current index of the program in the list of programs to be managed.
.PARAMETER totalPrograms
The total number of programs to be uninstalled.
.DESCRIPTION
This function uninstalls a Chocolatey package and any related metapackages (e.g., .install or .portable variants). It updates the taskbar progress after processing each package.
.EXAMPLE
Uninstall-ChocoPackage -Program $Program -currentIndex 0 -totalPrograms 5
#>
param (
[string]$Program,
[int]$currentIndex,
[int]$totalPrograms
)
$uninstallOutputFile = "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt"
Initialize-OutputFile $uninstallOutputFile
Write-Host "Searching for metapackages of $Program (.install or .portable)"
$chocoPackages = ((choco list | Select-String -Pattern "$Program(\.install|\.portable)?").Matches.Value) -join " "
if ($chocoPackages) {
Write-Host "Starting uninstallation of $chocoPackages with Chocolatey..."
try {
$uninstallStatusCode = Invoke-ChocoCommand "uninstall $chocoPackages -y"
Write-Host "$Program" $(if ($uninstallStatusCode -eq 0) { "uninstalled successfully." } else { "failed to uninstall." })
}
catch {
Write-Host "Failed to uninstall $Program due to an error: $_"
}
finally {
Update-TaskbarProgress $currentIndex $totalPrograms
}
}
else {
Write-Host "$Program is not installed."
}
}
$totalPrograms = $Programs.Count
if ($totalPrograms -le 0) {
throw "Parameter 'Programs' must have at least one item."
}
Write-Host "==========================================="
Write-Host "-- Configuring Chocolatey packages ---"
Write-Host "==========================================="
for ($currentIndex = 0; $currentIndex -lt $totalPrograms; $currentIndex++) {
$Program = $Programs[$currentIndex]
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($currentIndex / $totalPrograms * 100)
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)}
switch ($Action) {
"Install" {
Install-ChocoPackage -Program $Program -currentIndex $currentIndex -totalPrograms $totalPrograms
}
"Uninstall" {
Uninstall-ChocoPackage -Program $Program -currentIndex $currentIndex -totalPrograms $totalPrograms
}
default {
throw "Invalid action parameter value: '$Action'."
}
}
}
Set-WinUtilProgressBar -label "$($Action)ation done" -percent 100
# Cleanup Output Files
$outputFiles = @("$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt", "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt")
foreach ($filePath in $outputFiles) {
Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue
} }
} }
@@ -1,135 +1,16 @@
Function Install-WinUtilProgramWinget { Function Install-WinUtilProgramWinget {
<# param (
.SYNOPSIS [Parameter(Mandatory=$true)]
Runs the designated action on the provided programs using Winget
.PARAMETER Programs
A list of programs to process
.PARAMETER action
The action to perform on the programs, can be either 'Install' or 'Uninstall'
.NOTES
The triple quotes are required any time you need a " in a normal script block.
The winget Return codes are documented here: https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-actionr/winget/returnCodes.md
#>
param(
[Parameter(Mandatory, Position=0)]$Programs,
[Parameter(Mandatory, Position=1)]
[ValidateSet("Install", "Uninstall")] [ValidateSet("Install", "Uninstall")]
[String]$Action [string]$Action,
[Parameter(Mandatory=$true)]
[string[]]$Programs
) )
Function Invoke-Winget { if ($Action -eq 'Install') {
<# Start-Process -FilePath winget -ArgumentList "install $Programs --accept-package-agreements --source winget --silent" -NoNewWindow -Wait
.SYNOPSIS } else {
Invokes the winget.exe with the provided arguments and return the exit code Start-Process -FilePath winget -ArgumentList "uninstall $Programs --source winget --silent" -NoNewWindow -Wait
.PARAMETER wingetId
The Id of the Program that WinGet should Install/Uninstall
.NOTES
Invoke WinGet uses the public variable $Action defined outside the function to determine if a Program should be installed or removed
#>
param (
[string]$wingetId
)
$commonArguments = "--id $wingetId --silent"
$arguments = if ($Action -eq "Install") {
"install $commonArguments --accept-source-agreements --accept-package-agreements --source winget"
} else {
"uninstall $commonArguments --source winget"
}
$processParams = @{
FilePath = "winget"
ArgumentList = $arguments
Wait = $true
PassThru = $true
NoNewWindow = $true
}
return (Start-Process @processParams).ExitCode
} }
Function Invoke-Install {
<#
.SYNOPSIS
Contains the Install Logic and return code handling from winget
.PARAMETER Program
The WinGet ID of the Program that should be installed
#>
param (
[string]$Program
)
$status = Invoke-Winget -wingetId $Program
if ($status -eq 0) {
Write-Host "$($Program) installed successfully."
return $true
} elseif ($status -eq -1978335189) {
Write-Host "No applicable update found for $($Program)."
return $true
}
Write-Host "Failed to install $($Program)."
return $false
}
Function Invoke-Uninstall {
<#
.SYNOPSIS
Contains the Uninstall Logic and return code handling from WinGet
.PARAMETER Program
The WinGet ID of the Program that should be uninstalled
#>
param (
[string]$Program
)
try {
$status = Invoke-Winget -wingetId $Program
if ($status -eq 0) {
Write-Host "$($Program) uninstalled successfully."
return $true
} else {
Write-Host "Failed to uninstall $($Program)."
return $false
}
} catch {
Write-Host "Failed to uninstall $($Program) due to an error: $_"
return $false
}
}
$count = $Programs.Count
$failedPackages = @()
Write-Host "==========================================="
Write-Host "-- Configuring WinGet packages ---"
Write-Host "==========================================="
for ($i = 0; $i -lt $count; $i++) {
$Program = $Programs[$i]
$result = $false
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($i / $count * 100)
Invoke-WPFUIThread -ScriptBlock{ Set-WinUtilTaskbaritem -value ($i / $count)}
$result = switch ($Action) {
"Install" {Invoke-Install -Program $Program}
"Uninstall" {Invoke-Uninstall -Program $Program}
default {throw "[Install-WinUtilProgramWinget] Invalid action: $Action"}
}
if (-not $result) {
$failedPackages += $Program
}
}
Set-WinUtilProgressBar -label "$($Action) action done." -percent 100
return $failedPackages
} }
@@ -44,21 +44,18 @@ Function Invoke-WinUtilCurrentSystem {
if ($CheckBox -eq "tweaks") { if ($CheckBox -eq "tweaks") {
if (!(Test-Path 'HKU:\')) {$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)} if (!(Test-Path 'HKU:\')) {$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)}
$ScheduledTasks = Get-ScheduledTask
$sync.configs.tweaks | Get-Member -MemberType NoteProperty | ForEach-Object { $sync.configs.tweaks | Get-Member -MemberType NoteProperty | ForEach-Object {
$Config = $psitem.Name $Config = $psitem.Name
#WPFEssTweaksTele
$entry = $sync.configs.tweaks.$Config $entry = $sync.configs.tweaks.$Config
$registryKeys = $entry.registry $registryKeys = $entry.registry
$scheduledtaskKeys = $entry.scheduledtask
$serviceKeys = $entry.service $serviceKeys = $entry.service
$appxKeys = $entry.appx $appxKeys = $entry.appx
$invokeScript = $entry.InvokeScript $invokeScript = $entry.InvokeScript
$entryType = $entry.Type $entryType = $entry.Type
if ($registryKeys -or $scheduledtaskKeys -or $serviceKeys) { if ($registryKeys -or $serviceKeys) {
$Values = @() $Values = @()
if ($entryType -eq "Toggle") { if ($entryType -eq "Toggle") {
@@ -103,20 +100,6 @@ Function Invoke-WinUtilCurrentSystem {
} }
} }
Foreach ($tweaks in $scheduledtaskKeys) {
Foreach ($tweak in $tweaks) {
$task = $ScheduledTasks | Where-Object {$($psitem.TaskPath + $psitem.TaskName) -like "\$($tweak.name)"}
if ($task) {
$actualValue = $task.State
$expectedValue = $tweak.State
if ($expectedValue -ne $actualValue) {
$values += $False
}
}
}
}
Foreach ($tweaks in $serviceKeys) { Foreach ($tweaks in $serviceKeys) {
Foreach ($tweak in $tweaks) { Foreach ($tweak in $tweaks) {
$Service = Get-Service -Name $tweak.Name $Service = Get-Service -Name $tweak.Name
@@ -134,10 +117,6 @@ Function Invoke-WinUtilCurrentSystem {
if ($values -notcontains $false) { if ($values -notcontains $false) {
Write-Output $Config Write-Output $Config
} }
} else {
if ($invokeScript -or $appxKeys) {
Write-Debug "Skipping $Config in Get Installed: no detectable registry, scheduled task, or service state."
}
} }
} }
} }
@@ -1,49 +1,16 @@
function Invoke-WinUtilFeatureInstall { function Invoke-WinUtilFeatureInstall ($CheckBox) {
<#
.SYNOPSIS if ($sync.configs.feature.$CheckBox.feature) {
Converts all the values from the tweaks.json and routes them to the appropriate function foreach ($feature in $sync.configs.feature.$CheckBox.feature) {
Write-Host "Installing $feature"
#> Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart -ErrorAction Stop
param(
$CheckBox
)
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 ($CheckBox.Exception.Message -like "*requires elevation*") {
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
} else {
Write-Warning "Unable to Install $feature due to unhandled exception."
Write-Warning $CheckBox.Exception.StackTrace
}
}
} }
} }
if($sync.configs.feature.$CheckBox.InvokeScript) {
Foreach( $script in $sync.configs.feature.$CheckBox.InvokeScript ) {
try {
$Scriptblock = [scriptblock]::Create($script)
Write-Host "Running Script for $CheckBox" if ($sync.configs.feature.$CheckBox.InvokeScript) {
Invoke-Command $scriptblock -ErrorAction stop foreach ($script in $sync.configs.feature.$CheckBox.InvokeScript) {
} catch { Write-Host "Running Script for $CheckBox"
if ($CheckBox.Exception.Message -like "*requires elevation*") { Invoke-Command -ScriptBlock ([scriptblock]::Create($script)) -ErrorAction Stop
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
} else {
Invoke-WPFUIThread -ScriptBlock { Set-WinUtilTaskbaritem -state "Error" }
Write-Warning "Unable to Install $feature due to unhandled exception."
Write-Warning $CheckBox.Exception.StackTrace
}
}
} }
} }
} }
@@ -67,7 +67,6 @@ function Invoke-WinUtilFontScaling {
# Calculates and applies the new font size # Calculates and applies the new font size
$newValue = [math]::Round($originalValue * $ScaleFactor, 1) $newValue = [math]::Round($originalValue * $ScaleFactor, 1)
$sync.Form.Resources[$resourceName] = $newValue $sync.Form.Resources[$resourceName] = $newValue
Write-Debug "Scaled $resourceName from original $originalValue to $newValue (factor: $ScaleFactor)"
} }
} }
catch { catch {
@@ -80,8 +79,4 @@ function Invoke-WinUtilFontScaling {
$percentage = [math]::Round($ScaleFactor * 100) $percentage = [math]::Round($ScaleFactor * 100)
$sync.FontScalingValue.Text = "$percentage%" $sync.FontScalingValue.Text = "$percentage%"
} }
Write-Debug "Font scaling applied with factor: $ScaleFactor"
} }
+126 -39
View File
@@ -49,7 +49,7 @@ function Invoke-WinUtilISOMountAndVerify {
Set-WinUtilProgressBar -Label "Mounting ISO..." -Percent 10 Set-WinUtilProgressBar -Label "Mounting ISO..." -Percent 10
try { try {
Mount-DiskImage -ImagePath $isoPath -ErrorAction Stop | Out-Null Mount-DiskImage -ImagePath $isoPath
do { do {
Start-Sleep -Milliseconds 500 Start-Sleep -Milliseconds 500
@@ -64,7 +64,7 @@ function Invoke-WinUtilISOMountAndVerify {
$esdPath = Join-Path $driveLetter "sources\install.esd" $esdPath = Join-Path $driveLetter "sources\install.esd"
if (-not (Test-Path $wimPath) -and -not (Test-Path $esdPath)) { if (-not (Test-Path $wimPath) -and -not (Test-Path $esdPath)) {
Dismount-DiskImage -ImagePath $isoPath | Out-Null Dismount-DiskImage -ImagePath $isoPath
Write-Win11ISOLog "ERROR: install.wim/install.esd not found — not a valid Windows ISO." Write-Win11ISOLog "ERROR: install.wim/install.esd not found — not a valid Windows ISO."
[System.Windows.MessageBox]::Show( [System.Windows.MessageBox]::Show(
"This does not appear to be a valid Windows ISO.`n`ninstall.wim / install.esd was not found.", "This does not appear to be a valid Windows ISO.`n`ninstall.wim / install.esd was not found.",
@@ -79,7 +79,7 @@ function Invoke-WinUtilISOMountAndVerify {
$imageInfo = Get-WindowsImage -ImagePath $activeWim | Select-Object ImageIndex, ImageName $imageInfo = Get-WindowsImage -ImagePath $activeWim | Select-Object ImageIndex, ImageName
if (-not ($imageInfo | Where-Object { $_.ImageName -match "Windows 11" })) { if (-not ($imageInfo | Where-Object { $_.ImageName -match "Windows 11" })) {
Dismount-DiskImage -ImagePath $isoPath | Out-Null Dismount-DiskImage -ImagePath $isoPath
Write-Win11ISOLog "ERROR: No 'Windows 11' edition found in the image." Write-Win11ISOLog "ERROR: No 'Windows 11' edition found in the image."
[System.Windows.MessageBox]::Show( [System.Windows.MessageBox]::Show(
"No Windows 11 edition was found in this ISO.`n`nOnly official Windows 11 ISOs are supported.", "No Windows 11 edition was found in this ISO.`n`nOnly official Windows 11 ISOs are supported.",
@@ -151,7 +151,7 @@ function Invoke-WinUtilISOModify {
$sync["WPFWin11ISOModifyButton"].IsEnabled = $false $sync["WPFWin11ISOModifyButton"].IsEnabled = $false
$sync["Win11ISOModifying"] = $true $sync["Win11ISOModifying"] = $true
$existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") -ErrorAction SilentlyContinue | $existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") |
Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1 Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1
$workDir = if ($existingWorkDir) { $workDir = if ($existingWorkDir) {
@@ -202,7 +202,7 @@ function Invoke-WinUtilISOModify {
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length $sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd() $sync["WPFWin11ISOStatusLog"].ScrollToEnd()
}) })
Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg" -ErrorAction SilentlyContinue Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg"
} }
function SetProgress($label, $pct) { function SetProgress($label, $pct) {
@@ -213,6 +213,90 @@ function Invoke-WinUtilISOModify {
}) })
} }
function Get-DismImageInfoMap {
param(
[Parameter(Mandatory)][string]$ImagePath,
[int]$Index = 1
)
$map = @{}
$lines = & dism /English "/Get-ImageInfo" "/ImageFile:$ImagePath" "/Index:$Index"
foreach ($line in $lines) {
if ($line -match '^\s*([^:]+?)\s*:\s*(.*)$') {
$key = $Matches[1].Trim()
$val = $Matches[2].Trim()
if (-not $map.ContainsKey($key)) {
$map[$key] = $val
}
}
}
return $map
}
function Invoke-WinUtilWimMetadataHydration {
param(
[Parameter(Mandatory)][string]$ImagePath,
[Parameter(Mandatory)][string]$EditionName,
[scriptblock]$Logger
)
function LogMeta([string]$Message) {
if ($Logger) {
$null = $Logger.Invoke($Message)
}
}
$before = Get-DismImageInfoMap -ImagePath $ImagePath -Index 1
$undefinedBefore = @($before.GetEnumerator() | Where-Object { $_.Value -eq '<undefined>' } | ForEach-Object { $_.Key })
if ($undefinedBefore.Count -eq 0) {
LogMeta "Metadata check: no undefined DISM fields detected."
return
}
LogMeta "Metadata check: undefined DISM fields detected: $($undefinedBefore -join ', ')"
LogMeta "Attempting best-effort metadata hydration for install.wim..."
$setImage = Get-Command Set-WindowsImage -ErrorAction SilentlyContinue
if (-not $setImage) {
LogMeta "Set-WindowsImage is unavailable on this host; cannot write additional WIM metadata fields."
return
}
$targetName = if ($EditionName -and $EditionName -ne 'Unknown') { $EditionName } else { $before['Name'] }
if (-not $targetName) { $targetName = 'Windows 11' }
$targetDescription = if ($before['Description'] -and $before['Description'] -ne '<undefined>') {
$before['Description']
} else {
$targetName
}
$setArgs = @{
ImagePath = $ImagePath
Index = 1
Name = $targetName
Description = $targetDescription
ErrorAction = 'Stop'
}
try {
Set-WindowsImage @setArgs | Out-Null
LogMeta "Applied Set-WindowsImage metadata updates (Name/Description)."
} catch {
LogMeta "Warning: Set-WindowsImage metadata update failed: $_"
}
$after = Get-DismImageInfoMap -ImagePath $ImagePath -Index 1
$undefinedAfter = @($after.GetEnumerator() | Where-Object { $_.Value -eq '<undefined>' } | ForEach-Object { $_.Key })
if ($undefinedAfter.Count -eq 0) {
LogMeta "Metadata hydration complete: no undefined DISM fields remain."
} else {
LogMeta "Metadata hydration complete. Remaining undefined DISM fields: $($undefinedAfter -join ', ')"
LogMeta "Note: some DISM metadata fields are read-only and come from Microsoft image internals."
}
}
try { try {
$sync["WPFWin11ISOStatusLog"].Dispatcher.Invoke([action]{ $sync["WPFWin11ISOStatusLog"].Dispatcher.Invoke([action]{
$sync["WPFWin11ISOSelectSection"].Visibility = "Collapsed" $sync["WPFWin11ISOSelectSection"].Visibility = "Collapsed"
@@ -223,11 +307,11 @@ function Invoke-WinUtilISOModify {
Log "Creating working directory: $workDir" Log "Creating working directory: $workDir"
$isoContents = Join-Path $workDir "iso_contents" $isoContents = Join-Path $workDir "iso_contents"
$mountDir = Join-Path $workDir "wim_mount" $mountDir = Join-Path $workDir "wim_mount"
New-Item -ItemType Directory -Path $isoContents, $mountDir -Force | Out-Null New-Item -ItemType Directory -Path $isoContents, $mountDir -Force
SetProgress "Copying ISO contents..." 10 SetProgress "Copying ISO contents..." 10
Log "Copying ISO contents from $driveLetter to $isoContents..." Log "Copying ISO contents from $driveLetter to $isoContents..."
& robocopy $driveLetter $isoContents /E /NFL /NDL /NJH /NJS | Out-Null & robocopy $driveLetter $isoContents /E /NFL /NDL /NJH /NJS
Log "ISO contents copied." Log "ISO contents copied."
SetProgress "Mounting install.wim..." 25 SetProgress "Mounting install.wim..." 25
@@ -236,7 +320,7 @@ function Invoke-WinUtilISOModify {
Set-ItemProperty -Path $localWim -Name IsReadOnly -Value $false Set-ItemProperty -Path $localWim -Name IsReadOnly -Value $false
Log "Mounting install.wim (Index ${selectedWimIndex}: $selectedEditionName) at $mountDir..." Log "Mounting install.wim (Index ${selectedWimIndex}: $selectedEditionName) at $mountDir..."
Mount-WindowsImage -ImagePath $localWim -Index $selectedWimIndex -Path $mountDir -ErrorAction Stop | Out-Null Mount-WindowsImage -ImagePath $localWim -Index $selectedWimIndex -Path $mountDir
SetProgress "Modifying install.wim..." 45 SetProgress "Modifying install.wim..." 45
Log "Applying WinUtil modifications to install.wim..." Log "Applying WinUtil modifications to install.wim..."
@@ -249,21 +333,24 @@ function Invoke-WinUtilISOModify {
SetProgress "Saving modified install.wim..." 65 SetProgress "Saving modified install.wim..." 65
Log "Dismounting and saving install.wim. This will take several minutes..." Log "Dismounting and saving install.wim. This will take several minutes..."
Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $mountDir -Save
Log "install.wim saved." Log "install.wim saved."
SetProgress "Removing unused editions from install.wim..." 70 SetProgress "Removing unused editions from install.wim..." 70
Log "Exporting edition '$selectedEditionName' (Index $selectedWimIndex) to a single-edition install.wim..." Log "Exporting edition '$selectedEditionName' (Index $selectedWimIndex) to a single-edition install.wim..."
$exportWim = Join-Path $isoContents "sources\install_export.wim" $exportWim = Join-Path $isoContents "sources\install_export.wim"
Export-WindowsImage -SourceImagePath $localWim -SourceIndex $selectedWimIndex -DestinationImagePath $exportWim -ErrorAction Stop | Out-Null Export-WindowsImage -SourceImagePath $localWim -SourceIndex $selectedWimIndex -DestinationImagePath $exportWim
Remove-Item -Path $localWim -Force Remove-Item -Path $localWim -Force
Rename-Item -Path $exportWim -NewName "install.wim" -Force Rename-Item -Path $exportWim -NewName "install.wim" -Force
$localWim = Join-Path $isoContents "sources\install.wim" $localWim = Join-Path $isoContents "sources\install.wim"
Log "Unused editions removed. install.wim now contains only '$selectedEditionName'." Log "Unused editions removed. install.wim now contains only '$selectedEditionName'."
SetProgress "Hydrating WIM metadata..." 76
Invoke-WinUtilWimMetadataHydration -ImagePath $localWim -EditionName $selectedEditionName -Logger ${function:Log}
SetProgress "Dismounting source ISO..." 80 SetProgress "Dismounting source ISO..." 80
Log "Dismounting original ISO..." Log "Dismounting original ISO..."
Dismount-DiskImage -ImagePath $isoPath | Out-Null Dismount-DiskImage -ImagePath $isoPath
$sync["Win11ISOWorkDir"] = $workDir $sync["Win11ISOWorkDir"] = $workDir
$sync["Win11ISOContentsDir"] = $isoContents $sync["Win11ISOContentsDir"] = $isoContents
@@ -279,26 +366,26 @@ function Invoke-WinUtilISOModify {
try { try {
if (Test-Path $mountDir) { if (Test-Path $mountDir) {
$mountedImages = Get-WindowsImage -Mounted -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $mountDir } $mountedImages = Get-WindowsImage -Mounted | Where-Object { $_.Path -eq $mountDir }
if ($mountedImages) { if ($mountedImages) {
Log "Cleaning up: dismounting install.wim (discarding changes)..." Log "Cleaning up: dismounting install.wim (discarding changes)..."
Dismount-WindowsImage -Path $mountDir -Discard -ErrorAction SilentlyContinue | Out-Null Dismount-WindowsImage -Path $mountDir -Discard
} }
} }
} catch { Log "Warning: could not dismount install.wim during cleanup: $_" } } catch { Log "Warning: could not dismount install.wim during cleanup: $_" }
try { try {
$mountedISO = Get-DiskImage -ImagePath $isoPath -ErrorAction SilentlyContinue $mountedISO = Get-DiskImage -ImagePath $isoPath
if ($mountedISO -and $mountedISO.Attached) { if ($mountedISO -and $mountedISO.Attached) {
Log "Cleaning up: dismounting source ISO..." Log "Cleaning up: dismounting source ISO..."
Dismount-DiskImage -ImagePath $isoPath -ErrorAction SilentlyContinue | Out-Null Dismount-DiskImage -ImagePath $isoPath
} }
} catch { Log "Warning: could not dismount ISO during cleanup: $_" } } catch { Log "Warning: could not dismount ISO during cleanup: $_" }
try { try {
if (Test-Path $workDir) { if (Test-Path $workDir) {
Log "Cleaning up: removing temp directory $workDir..." Log "Cleaning up: removing temp directory $workDir..."
Remove-Item -Path $workDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $workDir -Recurse -Force
} }
} catch { Log "Warning: could not remove temp directory during cleanup: $_" } } catch { Log "Warning: could not remove temp directory during cleanup: $_" }
@@ -322,9 +409,9 @@ function Invoke-WinUtilISOModify {
} }
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
function Invoke-WinUtilISOCheckExistingWork { function Invoke-WinUtilISOCheckExistingWork {
@@ -335,7 +422,7 @@ function Invoke-WinUtilISOCheckExistingWork {
return return
} }
$existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") -ErrorAction SilentlyContinue | $existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") |
Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1 Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $existingWorkDir) { return } if (-not $existingWorkDir) { return }
@@ -391,7 +478,7 @@ function Invoke-WinUtilISOCleanAndReset {
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length $sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd() $sync["WPFWin11ISOStatusLog"].ScrollToEnd()
}) })
Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg" -ErrorAction SilentlyContinue Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg"
} }
function SetProgress($label, $pct) { function SetProgress($label, $pct) {
@@ -406,23 +493,23 @@ function Invoke-WinUtilISOCleanAndReset {
if ($workDir) { if ($workDir) {
$mountDir = Join-Path $workDir "wim_mount" $mountDir = Join-Path $workDir "wim_mount"
try { try {
$mountedImages = Get-WindowsImage -Mounted -ErrorAction SilentlyContinue | $mountedImages = Get-WindowsImage -Mounted |
Where-Object { $_.Path -like "$workDir*" } Where-Object { $_.Path -like "$workDir*" }
if ($mountedImages) { if ($mountedImages) {
foreach ($img in $mountedImages) { foreach ($img in $mountedImages) {
Log "Dismounting WIM at: $($img.Path) (discarding changes)..." Log "Dismounting WIM at: $($img.Path) (discarding changes)..."
SetProgress "Dismounting WIM image..." 3 SetProgress "Dismounting WIM image..." 3
Dismount-WindowsImage -Path $img.Path -Discard -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $img.Path -Discard
Log "WIM dismounted successfully." Log "WIM dismounted successfully."
} }
} elseif (Test-Path $mountDir) { } elseif (Test-Path $mountDir) {
Log "No mounted WIM reported by Get-WindowsImage. Running DISM /Cleanup-Wim as a precaution..." Log "No mounted WIM reported by Get-WindowsImage. Running DISM /Cleanup-Wim as a precaution..."
SetProgress "Running DISM cleanup..." 3 SetProgress "Running DISM cleanup..." 3
& dism /English /Cleanup-Wim 2>&1 | ForEach-Object { Log $_ } & dism /English /Cleanup-Wim | ForEach-Object { Log $_ }
} }
} catch { } catch {
Log "Warning: could not dismount WIM cleanly. Attempting DISM /Cleanup-Wim fallback: $_" Log "Warning: could not dismount WIM cleanly. Attempting DISM /Cleanup-Wim fallback: $_"
try { & dism /English /Cleanup-Wim 2>&1 | ForEach-Object { Log $_ } } try { & dism /English /Cleanup-Wim | ForEach-Object { Log $_ } }
catch { Log "Warning: DISM /Cleanup-Wim also failed: $_" } catch { Log "Warning: DISM /Cleanup-Wim also failed: $_" }
} }
} }
@@ -431,8 +518,8 @@ function Invoke-WinUtilISOCleanAndReset {
Log "Scanning files to delete in: $workDir" Log "Scanning files to delete in: $workDir"
SetProgress "Scanning files..." 5 SetProgress "Scanning files..." 5
$allFiles = @(Get-ChildItem -Path $workDir -File -Recurse -Force -ErrorAction SilentlyContinue) $allFiles = @(Get-ChildItem -Path $workDir -File -Recurse -Force)
$allDirs = @(Get-ChildItem -Path $workDir -Directory -Recurse -Force -ErrorAction SilentlyContinue | $allDirs = @(Get-ChildItem -Path $workDir -Directory -Recurse -Force |
Sort-Object { $_.FullName.Length } -Descending) Sort-Object { $_.FullName.Length } -Descending)
$total = $allFiles.Count $total = $allFiles.Count
$deleted = 0 $deleted = 0
@@ -440,7 +527,7 @@ function Invoke-WinUtilISOCleanAndReset {
Log "Found $total files to delete." Log "Found $total files to delete."
foreach ($f in $allFiles) { foreach ($f in $allFiles) {
try { Remove-Item -Path $f.FullName -Force -ErrorAction Stop } catch { Log "WARNING: could not delete $($f.FullName): $_" } try { Remove-Item -Path $f.FullName -Force } catch { Log "WARNING: could not delete $($f.FullName): $_" }
$deleted++ $deleted++
if ($deleted % 100 -eq 0 -or $deleted -eq $total) { if ($deleted % 100 -eq 0 -or $deleted -eq $total) {
$pct = [math]::Round(($deleted / [Math]::Max($total, 1)) * 85) + 5 $pct = [math]::Round(($deleted / [Math]::Max($total, 1)) * 85) + 5
@@ -449,10 +536,10 @@ function Invoke-WinUtilISOCleanAndReset {
} }
foreach ($d in $allDirs) { foreach ($d in $allDirs) {
try { Remove-Item -Path $d.FullName -Force -ErrorAction SilentlyContinue } catch {} try { Remove-Item -Path $d.FullName -Force } catch {}
} }
try { Remove-Item -Path $workDir -Recurse -Force -ErrorAction Stop } catch {} try { Remove-Item -Path $workDir -Recurse -Force } catch {}
if (Test-Path $workDir) { if (Test-Path $workDir) {
Log "WARNING: some items could not be deleted in $workDir" Log "WARNING: some items could not be deleted in $workDir"
@@ -501,9 +588,9 @@ function Invoke-WinUtilISOCleanAndReset {
$sync["WPFWin11ISOCleanResetButton"].IsEnabled = $true $sync["WPFWin11ISOCleanResetButton"].IsEnabled = $true
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
function Invoke-WinUtilISOExport { function Invoke-WinUtilISOExport {
@@ -529,10 +616,10 @@ function Invoke-WinUtilISOExport {
$outputISO = $dlg.FileName $outputISO = $dlg.FileName
# Locate oscdimg.exe (Windows ADK or winget per-user install) # Locate oscdimg.exe (Windows ADK or winget per-user install)
$oscdimg = Get-ChildItem "C:\Program Files (x86)\Windows Kits" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue | $oscdimg = Get-ChildItem "C:\Program Files (x86)\Windows Kits" -Recurse -Filter "oscdimg.exe" |
Select-Object -First 1 -ExpandProperty FullName Select-Object -First 1 -ExpandProperty FullName
if (-not $oscdimg) { if (-not $oscdimg) {
$oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue | $oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" |
Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } | Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } |
Select-Object -First 1 -ExpandProperty FullName Select-Object -First 1 -ExpandProperty FullName
} }
@@ -543,10 +630,10 @@ function Invoke-WinUtilISOExport {
# First ensure winget is installed and operational # First ensure winget is installed and operational
Install-WinUtilWinget Install-WinUtilWinget
$winget = Get-Command winget -ErrorAction Stop $winget = Get-Command winget
$result = & $winget install -e --id Microsoft.OSCDIMG --accept-package-agreements --accept-source-agreements 2>&1 $result = & $winget install -e --id Microsoft.OSCDIMG --accept-package-agreements --accept-source-agreements
Write-Win11ISOLog "winget output: $result" Write-Win11ISOLog "winget output: $result"
$oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue | $oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" |
Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } | Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } |
Select-Object -First 1 -ExpandProperty FullName Select-Object -First 1 -ExpandProperty FullName
} catch { } catch {
@@ -609,7 +696,7 @@ function Invoke-WinUtilISOExport {
$proc = [System.Diagnostics.Process]::new() $proc = [System.Diagnostics.Process]::new()
$proc.StartInfo = $psi $proc.StartInfo = $psi
$proc.Start() | Out-Null $proc.Start()
# Stream stdout line-by-line as oscdimg runs # Stream stdout line-by-line as oscdimg runs
while (-not $proc.StandardOutput.EndOfStream) { while (-not $proc.StandardOutput.EndOfStream) {
@@ -653,7 +740,7 @@ function Invoke-WinUtilISOExport {
$sync["WPFWin11ISOChooseISOButton"].IsEnabled = $true $sync["WPFWin11ISOChooseISOButton"].IsEnabled = $true
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
+23 -23
View File
@@ -84,27 +84,27 @@ function Invoke-WinUtilISOScript {
function Add-DriversToImage { function Add-DriversToImage {
param ([string]$MountPath, [string]$DriverDir, [string]$Label = "image", [scriptblock]$Logger) param ([string]$MountPath, [string]$DriverDir, [string]$Label = "image", [scriptblock]$Logger)
& dism /English "/image:$MountPath" /Add-Driver "/Driver:$DriverDir" /Recurse 2>&1 | & dism /English "/image:$MountPath" /Add-Driver "/Driver:$DriverDir" /Recurse |
ForEach-Object { & $Logger " dism[$Label]: $_" } ForEach-Object { & $Logger " dism[$Label]: $_" }
} }
function Invoke-BootWimInject { function Invoke-BootWimInject {
param ([string]$BootWimPath, [string]$DriverDir, [scriptblock]$Logger) param ([string]$BootWimPath, [string]$DriverDir, [scriptblock]$Logger)
Set-ItemProperty -Path $BootWimPath -Name IsReadOnly -Value $false -ErrorAction SilentlyContinue Set-ItemProperty -Path $BootWimPath -Name IsReadOnly -Value $false
$mountDir = Join-Path $env:TEMP "WinUtil_BootMount_$(Get-Random)" $mountDir = Join-Path $env:TEMP "WinUtil_BootMount_$(Get-Random)"
New-Item -Path $mountDir -ItemType Directory -Force | Out-Null New-Item -Path $mountDir -ItemType Directory -Force
try { try {
& $Logger "Mounting boot.wim (index 2) for driver injection..." & $Logger "Mounting boot.wim (index 2) for driver injection..."
Mount-WindowsImage -ImagePath $BootWimPath -Index 2 -Path $mountDir -ErrorAction Stop | Out-Null Mount-WindowsImage -ImagePath $BootWimPath -Index 2 -Path $mountDir
Add-DriversToImage -MountPath $mountDir -DriverDir $DriverDir -Label "boot" -Logger $Logger Add-DriversToImage -MountPath $mountDir -DriverDir $DriverDir -Label "boot" -Logger $Logger
& $Logger "Saving boot.wim..." & $Logger "Saving boot.wim..."
Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $mountDir -Save
& $Logger "boot.wim driver injection complete." & $Logger "boot.wim driver injection complete."
} catch { } catch {
& $Logger "Warning: boot.wim driver injection failed: $_" & $Logger "Warning: boot.wim driver injection failed: $_"
try { Dismount-WindowsImage -Path $mountDir -Discard -ErrorAction SilentlyContinue | Out-Null } catch {} try { Dismount-WindowsImage -Path $mountDir -Discard } catch {}
} finally { } finally {
Remove-Item -Path $mountDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $mountDir -Recurse -Force
} }
} }
@@ -143,9 +143,9 @@ function Invoke-WinUtilISOScript {
if ($InjectCurrentSystemDrivers) { if ($InjectCurrentSystemDrivers) {
& $Log "Exporting all drivers from running system..." & $Log "Exporting all drivers from running system..."
$driverExportRoot = Join-Path $env:TEMP "WinUtil_DriverExport_$(Get-Random)" $driverExportRoot = Join-Path $env:TEMP "WinUtil_DriverExport_$(Get-Random)"
New-Item -Path $driverExportRoot -ItemType Directory -Force | Out-Null New-Item -Path $driverExportRoot -ItemType Directory -Force
try { try {
Export-WindowsDriver -Online -Destination $driverExportRoot | Out-Null Export-WindowsDriver -Online -Destination $driverExportRoot
& $Log "Injecting current system drivers into install.wim..." & $Log "Injecting current system drivers into install.wim..."
Add-DriversToImage -MountPath $ScratchDir -DriverDir $driverExportRoot -Label "install" -Logger $Log Add-DriversToImage -MountPath $ScratchDir -DriverDir $driverExportRoot -Label "install" -Logger $Log
@@ -163,7 +163,7 @@ function Invoke-WinUtilISOScript {
} catch { } catch {
& $Log "Error during driver export/injection: $_" & $Log "Error during driver export/injection: $_"
} finally { } finally {
Remove-Item -Path $driverExportRoot -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $driverExportRoot -Recurse -Force
} }
} else { } else {
& $Log "Driver injection skipped." & $Log "Driver injection skipped."
@@ -231,7 +231,7 @@ function Invoke-WinUtilISOScript {
$absPath = $fileNode.GetAttribute("path") $absPath = $fileNode.GetAttribute("path")
$relPath = $absPath -replace '^[A-Za-z]:[/\\]', '' $relPath = $absPath -replace '^[A-Za-z]:[/\\]', ''
$destPath = Join-Path $ScratchDir $relPath $destPath = Join-Path $ScratchDir $relPath
New-Item -Path (Split-Path $destPath -Parent) -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null New-Item -Path (Split-Path $destPath -Parent) -ItemType Directory -Force
$ext = [IO.Path]::GetExtension($destPath).ToLower() $ext = [IO.Path]::GetExtension($destPath).ToLower()
$encoding = switch ($ext) { $encoding = switch ($ext) {
@@ -326,23 +326,23 @@ function Invoke-WinUtilISOScript {
# ── 4. Delete scheduled task definition files ───────────────────────────── # ── 4. Delete scheduled task definition files ─────────────────────────────
& $Log "Deleting scheduled task definition files..." & $Log "Deleting scheduled task definition files..."
$tasksPath = "$ScratchDir\Windows\System32\Tasks" $tasksPath = "$ScratchDir\Windows\System32\Tasks"
Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -Force
Remove-Item "$tasksPath\Microsoft\Windows\Customer Experience Improvement Program" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Customer Experience Improvement Program" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\ProgramDataUpdater" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\ProgramDataUpdater" -Force
Remove-Item "$tasksPath\Microsoft\Windows\Chkdsk\Proxy" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Chkdsk\Proxy" -Force
Remove-Item "$tasksPath\Microsoft\Windows\Windows Error Reporting\QueueReporting" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Windows Error Reporting\QueueReporting" -Force
Remove-Item "$tasksPath\Microsoft\Windows\InstallService" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\InstallService" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\UpdateOrchestrator" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\UpdateOrchestrator" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\UpdateAssistant" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\UpdateAssistant" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\WaaSMedic" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\WaaSMedic" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\WindowsUpdate" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\WindowsUpdate" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\WindowsUpdate" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\WindowsUpdate" -Recurse -Force
& $Log "Scheduled task files deleted." & $Log "Scheduled task files deleted."
# ── 5. Remove ISO support folder ───────────────────────────────────────── # ── 5. Remove ISO support folder ─────────────────────────────────────────
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) { if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
& $Log "Removing ISO support\ folder..." & $Log "Removing ISO support\ folder..."
Remove-Item -Path (Join-Path $ISOContentsDir "support") -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path $ISOContentsDir "support") -Recurse -Force
& $Log "ISO support\ folder removed." & $Log "ISO support\ folder removed."
} }
} }
+23 -23
View File
@@ -93,7 +93,7 @@ function Invoke-WinUtilISOWriteUSB {
} }
function Get-FreeDriveLetter { function Get-FreeDriveLetter {
$used = (Get-PSDrive -PSProvider FileSystem -ErrorAction SilentlyContinue).Name $used = (Get-PSDrive -PSProvider FileSystem).Name
foreach ($c in [char[]](68..90)) { foreach ($c in [char[]](68..90)) {
if ($used -notcontains [string]$c) { return $c } if ($used -notcontains [string]$c) { return $c }
} }
@@ -107,29 +107,29 @@ function Invoke-WinUtilISOWriteUSB {
$dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt" $dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII "select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII
Log "Running diskpart clean on Disk $diskNum..." Log "Running diskpart clean on Disk $diskNum..."
$dpCleanOut = diskpart /s $dpFile1 2>&1 $dpCleanOut = diskpart /s $dpFile1
$dpCleanOut | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" } $dpCleanOut | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
Remove-Item $dpFile1 -Force -ErrorAction SilentlyContinue Remove-Item $dpFile1 -Force
if (($dpCleanOut -join ' ') -match 'device is not ready') { if (($dpCleanOut -join ' ') -match 'device is not ready') {
Log "Disk $diskNum was not ready; waiting 5 seconds and retrying clean..." Log "Disk $diskNum was not ready; waiting 5 seconds and retrying clean..."
Start-Sleep -Seconds 5 Start-Sleep -Seconds 5
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
$dpFile1b = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt" $dpFile1b = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1b -Encoding ASCII "select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1b -Encoding ASCII
diskpart /s $dpFile1b 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" } diskpart /s $dpFile1b | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
Remove-Item $dpFile1b -Force -ErrorAction SilentlyContinue Remove-Item $dpFile1b -Force
} }
# Phase 2: Initialize as GPT # Phase 2: Initialize as GPT
Start-Sleep -Seconds 2 Start-Sleep -Seconds 2
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
$diskObj = Get-Disk -Number $diskNum -ErrorAction Stop $diskObj = Get-Disk -Number $diskNum
if ($diskObj.PartitionStyle -eq 'RAW') { if ($diskObj.PartitionStyle -eq 'RAW') {
Initialize-Disk -Number $diskNum -PartitionStyle GPT -ErrorAction Stop Initialize-Disk -Number $diskNum -PartitionStyle GPT
Log "Disk $diskNum initialized as GPT." Log "Disk $diskNum initialized as GPT."
} else { } else {
Set-Disk -Number $diskNum -PartitionStyle GPT -ErrorAction Stop Set-Disk -Number $diskNum -PartitionStyle GPT
Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))." Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))."
} }
@@ -138,7 +138,7 @@ function Invoke-WinUtilISOWriteUSB {
$volLabel = "W11-" + (Get-Date).ToString('yyMMdd') $volLabel = "W11-" + (Get-Date).ToString('yyMMdd')
$dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt" $dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt"
$maxFat32PartitionMB = 32768 $maxFat32PartitionMB = 32768
$diskSizeMB = [int][Math]::Floor((Get-Disk -Number $diskNum -ErrorAction Stop).Size / 1MB) $diskSizeMB = [int][Math]::Floor((Get-Disk -Number $diskNum).Size / 1MB)
$createPartitionCommand = "create partition primary" $createPartitionCommand = "create partition primary"
if ($diskSizeMB -gt $maxFat32PartitionMB) { if ($diskSizeMB -gt $maxFat32PartitionMB) {
$createPartitionCommand = "create partition primary size=$maxFat32PartitionMB" $createPartitionCommand = "create partition primary size=$maxFat32PartitionMB"
@@ -151,14 +151,14 @@ function Invoke-WinUtilISOWriteUSB {
"exit" "exit"
) | Set-Content -Path $dpFile2 -Encoding ASCII ) | Set-Content -Path $dpFile2 -Encoding ASCII
Log "Creating partitions on Disk $diskNum..." Log "Creating partitions on Disk $diskNum..."
diskpart /s $dpFile2 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" } diskpart /s $dpFile2 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
Remove-Item $dpFile2 -Force -ErrorAction SilentlyContinue Remove-Item $dpFile2 -Force
SetProgress "Formatting USB partition..." 25 SetProgress "Formatting USB partition..." 25
Start-Sleep -Seconds 3 Start-Sleep -Seconds 3
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
$partitions = Get-Partition -DiskNumber $diskNum -ErrorAction Stop $partitions = Get-Partition -DiskNumber $diskNum
Log "Partitions on Disk $diskNum after creation: $($partitions.Count)" Log "Partitions on Disk $diskNum after creation: $($partitions.Count)"
foreach ($p in $partitions) { foreach ($p in $partitions) {
Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB" Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB"
@@ -173,14 +173,14 @@ function Invoke-WinUtilISOWriteUSB {
# with 'no volume selected' when the partition has never been formatted before) # with 'no volume selected' when the partition has never been formatted before)
Log "Formatting Partition $($winpePart.PartitionNumber) as FAT32 (label: $volLabel)..." Log "Formatting Partition $($winpePart.PartitionNumber) as FAT32 (label: $volLabel)..."
Get-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber | Get-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber |
Format-Volume -FileSystem FAT32 -NewFileSystemLabel $volLabel -Force -Confirm:$false | Out-Null Format-Volume -FileSystem FAT32 -NewFileSystemLabel $volLabel -Force -Confirm:$false
Log "Partition $($winpePart.PartitionNumber) formatted as FAT32." Log "Partition $($winpePart.PartitionNumber) formatted as FAT32."
SetProgress "Assigning drive letters..." 30 SetProgress "Assigning drive letters..." 30
Start-Sleep -Seconds 2 Start-Sleep -Seconds 2
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" -ErrorAction SilentlyContinue } catch {} try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" } catch {}
$usbLetter = Get-FreeDriveLetter $usbLetter = Get-FreeDriveLetter
if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." } if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." }
Set-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -NewDriveLetter $usbLetter Set-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -NewDriveLetter $usbLetter
@@ -197,9 +197,9 @@ function Invoke-WinUtilISOWriteUSB {
if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." } if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." }
Log "USB data partition: $usbDrive" Log "USB data partition: $usbDrive"
$contentSizeBytes = (Get-ChildItem -LiteralPath $contentsDir -File -Recurse -Force -ErrorAction Stop | Measure-Object -Property Length -Sum).Sum $contentSizeBytes = (Get-ChildItem -LiteralPath $contentsDir -File -Recurse -Force | Measure-Object -Property Length -Sum).Sum
if (-not $contentSizeBytes) { $contentSizeBytes = 0 } if (-not $contentSizeBytes) { $contentSizeBytes = 0 }
$usbVolume = Get-Volume -DriveLetter $usbLetter -ErrorAction Stop $usbVolume = Get-Volume -DriveLetter $usbLetter
$partitionCapacityBytes = [int64]$usbVolume.Size $partitionCapacityBytes = [int64]$usbVolume.Size
$partitionFreeBytes = [int64]$usbVolume.SizeRemaining $partitionFreeBytes = [int64]$usbVolume.SizeRemaining
@@ -226,7 +226,7 @@ function Invoke-WinUtilISOWriteUSB {
if ($wimSizeMB -gt 3800) { if ($wimSizeMB -gt 3800) {
Log "install.wim is $wimSizeMB MB - splitting for FAT32 compatibility... This will take several minutes." Log "install.wim is $wimSizeMB MB - splitting for FAT32 compatibility... This will take several minutes."
$splitDest = Join-Path $usbDrive "sources\install.swm" $splitDest = Join-Path $usbDrive "sources\install.swm"
New-Item -ItemType Directory -Path (Split-Path $splitDest) -Force | Out-Null New-Item -ItemType Directory -Path (Split-Path $splitDest) -Force
Split-WindowsImage -ImagePath $installWim -SplitImagePath $splitDest -FileSize 3800 -CheckIntegrity Split-WindowsImage -ImagePath $installWim -SplitImagePath $splitDest -FileSize 3800 -CheckIntegrity
Log "install.wim split complete." Log "install.wim split complete."
Log "Copying remaining files to USB..." Log "Copying remaining files to USB..."
@@ -262,7 +262,7 @@ function Invoke-WinUtilISOWriteUSB {
$sync["WPFWin11ISOWriteUSBButton"].IsEnabled = $true $sync["WPFWin11ISOWriteUSBButton"].IsEnabled = $true
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
@@ -1,8 +1,15 @@
function Invoke-WinUtilInstallPSProfile { function Invoke-WinUtilInstallPSProfile {
if (-not (Get-Command wt)) {
if (Test-Path $Profile) { Write-Host "Windows Terminal not found installing..."
Rename-Item $Profile -NewName ($Profile + '.bak') Install-WinUtilWinget
winget install Microsoft.WindowsTerminal --source winget --silent
} }
Start-Process pwsh -ArgumentList '-Command "irm https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1 | iex"' if (-not (Get-Command pwsh)) {
Write-Host "Powershell 7 not found installing..."
Install-WinUtilWinget
winget install Microsoft.PowerShell --source winget --silent
}
wt new-tab pwsh -NoExit -Command "irm https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1 | iex"
} }
+7 -31
View File
@@ -21,11 +21,9 @@ function Invoke-WinUtilTweaks {
$KeepServiceStartup = $true $KeepServiceStartup = $true
) )
Write-Debug "Tweaks: $($CheckBox)" if ($undo) {
if($undo) {
$Values = @{ $Values = @{
Registry = "OriginalValue" Registry = "OriginalValue"
ScheduledTask = "OriginalState"
Service = "OriginalType" Service = "OriginalType"
ScriptType = "UndoScript" ScriptType = "UndoScript"
} }
@@ -33,30 +31,21 @@ function Invoke-WinUtilTweaks {
} else { } else {
$Values = @{ $Values = @{
Registry = "Value" Registry = "Value"
ScheduledTask = "State"
Service = "StartupType" Service = "StartupType"
OriginalService = "OriginalType" OriginalService = "OriginalType"
ScriptType = "InvokeScript" ScriptType = "InvokeScript"
} }
} }
if($sync.configs.tweaks.$CheckBox.ScheduledTask) { if ($sync.configs.tweaks.$CheckBox.service) {
$sync.configs.tweaks.$CheckBox.ScheduledTask | ForEach-Object {
Write-Debug "$($psitem.Name) and state is $($psitem.$($values.ScheduledTask))"
Set-WinUtilScheduledTask -Name $psitem.Name -State $psitem.$($values.ScheduledTask)
}
}
if($sync.configs.tweaks.$CheckBox.service) {
Write-Debug "KeepServiceStartup is $KeepServiceStartup"
$sync.configs.tweaks.$CheckBox.service | ForEach-Object { $sync.configs.tweaks.$CheckBox.service | ForEach-Object {
$changeservice = $true $changeservice = $true
# The check for !($undo) is required, without it the script will throw an error for accessing unavailable member, which's the 'OriginalService' Property # The check for !($undo) is required, without it the script will throw an error for accessing unavailable member, which's the 'OriginalService' Property
if($KeepServiceStartup -AND !($undo)) { if ($KeepServiceStartup -AND !($undo)) {
try { try {
# Check if the service exists # Check if the service exists
$service = Get-Service -Name $psitem.Name -ErrorAction Stop $service = Get-Service -Name $psitem.Name -ErrorAction Stop
if(!($service.StartType.ToString() -eq $psitem.$($values.OriginalService))) { if(!($service.StartType.ToString() -eq $psitem.$($values.OriginalService))) {
Write-Debug "Service $($service.Name) was changed in the past to $($service.StartType.ToString()) from it's original type of $($psitem.$($values.OriginalService)), will not change it to $($psitem.$($values.service))"
$changeservice = $false $changeservice = $false
} }
} catch [System.ServiceProcess.ServiceNotFoundException] { } catch [System.ServiceProcess.ServiceNotFoundException] {
@@ -64,41 +53,28 @@ function Invoke-WinUtilTweaks {
} }
} }
if($changeservice) { if ($changeservice) {
Write-Debug "$($psitem.Name) and state is $($psitem.$($values.service))"
Set-WinUtilService -Name $psitem.Name -StartupType $psitem.$($values.Service) Set-WinUtilService -Name $psitem.Name -StartupType $psitem.$($values.Service)
} }
} }
} }
if($sync.configs.tweaks.$CheckBox.registry) { if ($sync.configs.tweaks.$CheckBox.registry) {
$sync.configs.tweaks.$CheckBox.registry | ForEach-Object { $sync.configs.tweaks.$CheckBox.registry | ForEach-Object {
Write-Debug "$($psitem.Name) and state is $($psitem.$($values.registry))"
if (($psitem.Path -imatch "hku") -and !(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)
if (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue) {
Write-Debug "HKU drive created successfully."
} else {
Write-Debug "Failed to create HKU drive."
}
}
Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry) Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry)
} }
} }
if($sync.configs.tweaks.$CheckBox.$($values.ScriptType)) { if ($sync.configs.tweaks.$CheckBox.$($values.ScriptType)) {
$sync.configs.tweaks.$CheckBox.$($values.ScriptType) | ForEach-Object { $sync.configs.tweaks.$CheckBox.$($values.ScriptType) | ForEach-Object {
Write-Debug "$($psitem) and state is $($psitem.$($values.ScriptType))"
$Scriptblock = [scriptblock]::Create($psitem) $Scriptblock = [scriptblock]::Create($psitem)
Invoke-WinUtilScript -ScriptBlock $scriptblock -Name $CheckBox Invoke-WinUtilScript -ScriptBlock $scriptblock -Name $CheckBox
} }
} }
if(!$undo) { if (!$undo) {
if($sync.configs.tweaks.$CheckBox.appx) { if($sync.configs.tweaks.$CheckBox.appx) {
$sync.configs.tweaks.$CheckBox.appx | ForEach-Object { $sync.configs.tweaks.$CheckBox.appx | ForEach-Object {
Write-Debug "UNDO $($psitem.Name)"
Remove-WinUtilAPPX -Name $psitem Remove-WinUtilAPPX -Name $psitem
} }
} }
} }
} }
@@ -1,10 +1,9 @@
function Invoke-WinUtilUninstallPSProfile { function Invoke-WinUtilUninstallPSProfile {
if (Test-Path ($Profile + '.bak')) {
Remove-Item $Profile if (Test-Path ($Profile + ".bak")) {
Rename-Item ($Profile + '.bak') -NewName $Profile Move-Item -Path ($Profile + ".bak") -Destination $Profile
} } else {
else { Remove-Item -Path $Profile
Remove-Item $Profile
} }
Write-Host "Successfully uninstalled CTT PowerShell Profile." -ForegroundColor Green Write-Host "Successfully uninstalled CTT PowerShell Profile." -ForegroundColor Green
-11
View File
@@ -23,14 +23,6 @@ function Reset-WPFCheckBoxes {
$CheckBoxesToCheck = $sync.selectedApps + $sync.selectedTweaks + $sync.selectedFeatures $CheckBoxesToCheck = $sync.selectedApps + $sync.selectedTweaks + $sync.selectedFeatures
$CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"} $CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
Write-Debug "Getting checkboxes to set, number of checkboxes: $($CheckBoxes.Count)"
if ($CheckBoxesToCheck -ne "") {
$debugMsg = "CheckBoxes to Check are: "
$CheckBoxesToCheck | ForEach-Object { $debugMsg += "$_, " }
$debugMsg = $debugMsg -replace (',\s*$', '')
Write-Debug "$debugMsg"
}
foreach ($CheckBox in $CheckBoxes) { foreach ($CheckBox in $CheckBoxes) {
$checkboxName = $CheckBox.Key $checkboxName = $CheckBox.Key
@@ -43,11 +35,9 @@ function Reset-WPFCheckBoxes {
if ($CheckBoxesToCheck -contains $checkboxName) { if ($CheckBoxesToCheck -contains $checkboxName) {
# If it exists, set IsChecked to true # If it exists, set IsChecked to true
$sync.$checkboxName.IsChecked = $true $sync.$checkboxName.IsChecked = $true
Write-Debug "$checkboxName is checked"
} else { } else {
# If it doesn't exist, set IsChecked to false # If it doesn't exist, set IsChecked to false
$sync.$checkboxName.IsChecked = $false $sync.$checkboxName.IsChecked = $false
Write-Debug "$checkboxName is not checked"
} }
} }
@@ -68,7 +58,6 @@ function Reset-WPFCheckBoxes {
foreach ($toggle in $allToggles) { foreach ($toggle in $allToggles) {
if ($importedToggles -contains $toggle.Key) { if ($importedToggles -contains $toggle.Key) {
$sync[$toggle.Key].IsChecked = $true $sync[$toggle.Key].IsChecked = $true
Write-Debug "Restoring toggle: $($toggle.Key) = checked"
} }
# Toggles not present in the import are intentionally left untouched; # Toggles not present in the import are intentionally left untouched;
# their current UI state already reflects the real system state. # their current UI state already reflects the real system state.
-2
View File
@@ -34,7 +34,6 @@ function Set-Preferences{
$ini = "" $ini = ""
foreach($key in $sync.preferences.Keys) { foreach($key in $sync.preferences.Keys) {
$pref = "$($key)=$($sync.preferences.$key)" $pref = "$($key)=$($sync.preferences.$key)"
Write-Debug "Saving pref: $($pref)"
$ini = $ini + $pref + "`r`n" $ini = $ini + $pref + "`r`n"
} }
$ini | Out-File $iniPath $ini | Out-File $iniPath
@@ -49,7 +48,6 @@ function Set-Preferences{
$arr = $line -split "=",-2 $arr = $line -split "=",-2
$key = $arr[0] -replace "\s","" $key = $arr[0] -replace "\s",""
$value = $arr[1] -replace "\s","" $value = $arr[1] -replace "\s",""
Write-Debug "Preference: Key = '$($key)' Value ='$($value)'"
$sync.preferences.$key = $value $sync.preferences.$key = $value
} }
} }
@@ -1,42 +0,0 @@
function Set-WinUtilScheduledTask {
<#
.SYNOPSIS
Enables/Disables the provided Scheduled Task
.PARAMETER Name
The path to the Scheduled Task
.PARAMETER State
The State to set the Task to
.EXAMPLE
Set-WinUtilScheduledTask -Name "Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -State "Disabled"
#>
param (
$Name,
$State
)
try {
if($State -eq "Disabled") {
Write-Host "Disabling Scheduled Task $Name"
Disable-ScheduledTask -TaskName $Name -ErrorAction Stop
}
if($State -eq "Enabled") {
Write-Host "Enabling Scheduled Task $Name"
Enable-ScheduledTask -TaskName $Name -ErrorAction Stop
}
} catch [System.Exception] {
if($psitem.Exception.Message -like "*The system cannot find the file specified*") {
Write-Warning "Scheduled Task $Name was not found."
} else {
Write-Warning "Unable to set $Name due to unhandled exception."
Write-Warning $psitem.Exception.Message
}
} catch {
Write-Warning "Unable to run script for $name due to unhandled exception."
Write-Warning $psitem.Exception.StackTrace
}
}
@@ -1,21 +0,0 @@
Function Update-WinUtilProgramWinget {
<#
.SYNOPSIS
This will update all programs using WinGet
#>
[ScriptBlock]$wingetinstall = {
$host.ui.RawUI.WindowTitle = """WinGet Install"""
Start-Transcript "$logdir\winget-update_$dateTime.log" -Append
winget upgrade --all --accept-source-agreements --accept-package-agreements --scope=machine --silent
}
$global:WinGetInstall = Start-Process -Verb runas powershell -ArgumentList "-command invoke-command -scriptblock {$wingetinstall} -argumentlist '$($ProgramsToInstall -join ",")'" -PassThru
}
@@ -12,8 +12,6 @@ function Update-WinUtilSelections {
$flatJson $flatJson
) )
Write-Debug "JSON to import: $($flatJson)"
foreach ($item in $flatJson) { foreach ($item in $flatJson) {
# Ensure each item is treated as a string to handle PSCustomObject from JSON deserialization # Ensure each item is treated as a string to handle PSCustomObject from JSON deserialization
$cbkey = [string]$item $cbkey = [string]$item
@@ -51,11 +49,4 @@ function Update-WinUtilSelections {
} }
} }
} }
Write-Debug "-------------------------------------"
Write-Debug "Selected Apps: $($sync.selectedApps)"
Write-Debug "Selected Tweaks: $($sync.selectedTweaks)"
Write-Debug "Selected Toggles: $($sync.selectedToggles)"
Write-Debug "Selected Features: $($sync.selectedFeatures)"
Write-Debug "--------------------------------------"
} }
+1
View File
@@ -65,6 +65,7 @@ function Invoke-WPFButton {
"WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"} "WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"}
"WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"} "WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"}
"WPFCloseButton" {$sync.Form.Close(); Write-Host "Bye bye!"} "WPFCloseButton" {$sync.Form.Close(); Write-Host "Bye bye!"}
"WPFMinimizeButton" {$sync.Form.WindowState = [Windows.WindowState]::Minimized}
"WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen} "WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen}
"WPFToggleFOSSHighlight" { "WPFToggleFOSSHighlight" {
if ($sync.WPFToggleFOSSHighlight.IsChecked) { if ($sync.WPFToggleFOSSHighlight.IsChecked) {
+12 -27
View File
@@ -1,36 +1,21 @@
function Invoke-WPFInstallUpgrade { function Invoke-WPFInstallUpgrade {
<#
.SYNOPSIS
Invokes the function that upgrades all installed programs
#>
if ($sync.ChocoRadioButton.IsChecked) { if ($sync.ChocoRadioButton.IsChecked) {
Install-WinUtilChoco Install-WinUtilChoco # Ensure Chocolatey is installed before upgrading
$chocoUpgradeStatus = (Start-Process "choco" -ArgumentList "upgrade all -y" -Wait -PassThru -NoNewWindow).ExitCode
if ($chocoUpgradeStatus -eq 0) {
Write-Host "Upgrade Successful"
}
else{
Write-Host "Error Occurred. Return Code: $chocoUpgradeStatus"
}
}
else{
if((Test-WinUtilPackageManager -winget) -eq "not-installed") {
return
}
if(Get-WinUtilInstallerProcess -Process $global:WinGetInstall) {
$msg = "[Invoke-WPFInstallUpgrade] Install process is currently running. Please check for a powershell window labeled 'Winget Install'"
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
return
}
Update-WinUtilProgramWinget
Write-Host "===========================================" Write-Host "==========================================="
Write-Host "-- Updates started ---" Write-Host "-- Updates started ---"
Write-Host "-- You can close this window if desired ---" Write-Host "-- You can close this window if desired ---"
Write-Host "===========================================" Write-Host "==========================================="
Start-Process -FilePath powershell.exe -ArgumentList 'choco upgrade all -y'
} else {
Install-WinUtilWinget # Ensure WinGet is installed before upgrading
Write-Host "==========================================="
Write-Host "-- Updates started ---"
Write-Host "-- You can close this window if desired ---"
Write-Host "==========================================="
Start-Process -FilePath powershell.exe -ArgumentList 'winget upgrade --all --include-unknown --silent --accept-source-agreements --accept-package-agreements'
} }
} }
@@ -85,11 +85,4 @@ function Invoke-WPFSelectedCheckboxesUpdate{
Write-Host "Unknown group for checkbox: $($appKey)" Write-Host "Unknown group for checkbox: $($appKey)"
} }
} }
Write-Debug "-------------------------------------"
Write-Debug "Selected Apps: $($sync.selectedApps)"
Write-Debug "Selected Tweaks: $($sync.selectedTweaks)"
Write-Debug "Selected Toggles: $($sync.selectedToggles)"
Write-Debug "Selected Features: $($sync.selectedFeatures)"
Write-Debug "--------------------------------------"
} }

Some files were not shown because too many files have changed in this diff Show More