mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-08-09 17:41:14 +10:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93dc23dd66 | ||
|
|
916dc761ba | ||
|
|
2cb20893fc | ||
|
|
c3b4f85fce | ||
|
|
104c763132 | ||
|
|
8062815655 | ||
|
|
58be808823 | ||
|
|
77dc64cbea | ||
|
|
72d47ba020 | ||
|
|
b6b479685a | ||
|
|
c7dfbeb7fe | ||
|
|
7c71a39f7a | ||
|
|
0c42b9e458 | ||
|
|
26f89adf95 | ||
|
|
5003f14e0a | ||
|
|
8b6098b36a | ||
|
|
1f0756336f | ||
|
|
0f39648de6 | ||
|
|
7f0d2183e3 | ||
|
|
6ae24d071d |
@@ -81,7 +81,7 @@ jobs:
|
||||
run: "cd docs && [[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
|
||||
- name: Cache Restore
|
||||
id: cache-restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: |
|
||||
${{ runner.temp }}/hugo_cache
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
--cacheDir "${{ runner.temp }}/hugo_cache"
|
||||
- name: Cache Save
|
||||
id: cache-save
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@v6
|
||||
with:
|
||||
path: |
|
||||
${{ runner.temp }}/hugo_cache
|
||||
|
||||
@@ -27,13 +27,16 @@ jobs:
|
||||
- name: Install Pester
|
||||
run: |
|
||||
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
|
||||
Install-Module -Name Pester -Force -SkipPublisherCheck -AllowClobber
|
||||
Install-Module -Name Pester -RequiredVersion 5.8.0 -Force -SkipPublisherCheck -AllowClobber
|
||||
Import-Module Pester -RequiredVersion 5.8.0 -Force
|
||||
Get-Module Pester | Select-Object Name, Version, Path
|
||||
shell: pwsh
|
||||
|
||||
- name: Run Pester tests
|
||||
run: |
|
||||
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
|
||||
Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed
|
||||
Import-Module Pester -RequiredVersion 5.8.0 -Force
|
||||
Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed -CI
|
||||
|
||||
shell: pwsh
|
||||
env:
|
||||
|
||||
@@ -5,6 +5,7 @@ Microsoft.PowerShell.ConsoleHost.dll
|
||||
winutil.exe.config
|
||||
winutil.ps1
|
||||
binary/
|
||||
testResults.xml
|
||||
|
||||
# general software/os specific
|
||||
desktop.ini
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
# AGENTS.md
|
||||
|
||||
Drop-in operating instructions for coding agents. Read this file before every task.
|
||||
|
||||
**Working code only. Finish the job. Plausibility is not correctness.**
|
||||
|
||||
This repository follows the AGENTS.md convention: these instructions are for Codex, Claude Code, Cursor, Windsurf, Copilot, Aider, Devin, Amp, and other coding agents that read `AGENTS.md`.
|
||||
|
||||
## 0. Non-Negotiables
|
||||
|
||||
These rules override everything else in this file when in conflict:
|
||||
|
||||
1. **Do not edit `winutil.ps1` directly.** It is generated build output. Change source files and compile.
|
||||
2. **Do not commit `winutil.ps1`.** It is ignored locally and generated by GitHub Actions for releases.
|
||||
3. **Never fabricate.** Do not invent file paths, function names, command output, test results, commit hashes, or API behavior. Read the file or run the command.
|
||||
4. **Disagree when the premise is wrong.** Say what is wrong before acting on it.
|
||||
5. **Stop when genuinely ambiguous.** If two interpretations would produce materially different diffs, ask before editing.
|
||||
6. **Touch only what the task requires.** No drive-by refactors, formatting sweeps, or unrelated cleanup.
|
||||
7. **Verify before saying done.** A plausible-looking diff is not proof.
|
||||
|
||||
## 1. Project Context
|
||||
|
||||
WinUtil is a Windows PowerShell utility with a WPF interface. The repository is maintained as modular source, but the distributed artifact is one compiled PowerShell script.
|
||||
|
||||
### Stack
|
||||
|
||||
- Language: Windows PowerShell / PowerShell.
|
||||
- UI: WPF via `xaml/inputXML.xaml`.
|
||||
- Configuration: JSON files under `config/`.
|
||||
- Tests: Pester tests under `pester/`.
|
||||
- Lint: PowerShell Script Analyzer with settings in `lint/PSScriptAnalyser.ps1`.
|
||||
- Docs: Hugo site under `docs/`.
|
||||
- Release artifact: generated root `winutil.ps1`.
|
||||
|
||||
### Key Commands
|
||||
|
||||
- Compile:
|
||||
```powershell
|
||||
.\Compile.ps1
|
||||
```
|
||||
- Compile and run GUI:
|
||||
```powershell
|
||||
.\Compile.ps1 -Run
|
||||
```
|
||||
- Run tests:
|
||||
```powershell
|
||||
Import-Module Pester -RequiredVersion 5.8.0 -Force
|
||||
Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed
|
||||
```
|
||||
- Run Script Analyzer with project settings when available:
|
||||
```powershell
|
||||
Invoke-ScriptAnalyzer -Path . -Settings .\lint\PSScriptAnalyser.ps1 -Recurse
|
||||
```
|
||||
|
||||
Prefer the narrowest useful verification while iterating. Use the full relevant check before finishing.
|
||||
|
||||
## 2. Source Of Truth
|
||||
|
||||
Make durable changes only in files consumed by `Compile.ps1` or in documentation/test files:
|
||||
|
||||
- `scripts/start.ps1` for startup/bootstrap code.
|
||||
- `functions/public/*.ps1` for UI-facing and user-facing workflows.
|
||||
- `functions/private/*.ps1` for internal helpers.
|
||||
- `config/*.json` for applications, tweaks, features, DNS, presets, navigation, themes, and related declarative data.
|
||||
- `xaml/inputXML.xaml` for the WPF UI layout.
|
||||
- `tools/autounattend.xml` for the embedded unattended Windows setup template.
|
||||
- `scripts/main.ps1` for the final entrypoint and GUI initialization logic appended during compile.
|
||||
- `pester/*.Tests.ps1` for automated checks.
|
||||
- `docs/` for Hugo documentation.
|
||||
|
||||
If behavior changes require the compiled script to change, update these source files and run `.\Compile.ps1` only to verify generation.
|
||||
|
||||
## 3. Build Model
|
||||
|
||||
`Compile.ps1` combines the repository sources into `winutil.ps1` in this order:
|
||||
|
||||
1. Read `scripts/start.ps1` and replace `#{replaceme}` with the current `yy.MM.dd` build date.
|
||||
2. Append every file under `functions/` recursively.
|
||||
3. Convert each `config/*.json` file into embedded `$sync.configs` objects.
|
||||
4. Special-case `config/applications.json` so keys receive the `WPFInstall` prefix in compiled config.
|
||||
5. Embed `xaml/inputXML.xaml` into `$inputXML`.
|
||||
6. Embed `tools/autounattend.xml` into `$WinUtilAutounattendXml`.
|
||||
7. Append `scripts/main.ps1`.
|
||||
8. Write the result to root `winutil.ps1`.
|
||||
|
||||
Because the final script is concatenated, do not rely on runtime module imports or source-relative dot-sourcing unless the compiled script will also contain the required code/data.
|
||||
|
||||
## 4. Before Editing
|
||||
|
||||
- State the plan in one or two sentences before editing. For non-trivial work, include the verification you intend to run.
|
||||
- Read the files you will touch and the files that call them.
|
||||
- Match existing patterns even when a different greenfield design would be cleaner.
|
||||
- Surface assumptions when they affect behavior, compatibility, or user data.
|
||||
- If two approaches have meaningful tradeoffs, name them before choosing. Trivial tasks can proceed directly.
|
||||
|
||||
## 5. Coding Guidelines
|
||||
|
||||
- Prefer the minimum code that solves the stated problem.
|
||||
- Keep PowerShell functions in one function file when practical, with the file name matching the primary function name.
|
||||
- Use approved PowerShell verb-noun names and follow the existing `WPF` / `WinUtil` naming conventions.
|
||||
- Keep UI event handler names aligned with XAML element names. A button named `WPFExampleButton` is typically handled by `Invoke-WPFExampleButton`.
|
||||
- Use `$sync` for shared state and UI references, consistent with the existing runspace model.
|
||||
- Update WPF controls through the UI dispatcher when running work in a background runspace.
|
||||
- Keep config-driven features in JSON when they fit the existing schema instead of hard-coding lists in PowerShell.
|
||||
- Preserve undo/original-state data for tweaks so users can reverse changes.
|
||||
- Do not add abstractions, configurability, hooks, or "future extensibility" unless the task needs them now.
|
||||
- Clean up orphans created by your own changes, such as unused variables or functions made obsolete by the edit.
|
||||
- Avoid broad formatting-only edits, especially in JSON config files, XAML, docs, and generated output.
|
||||
|
||||
## 6. Runtime And Safety Rules
|
||||
|
||||
- WinUtil performs system-level Windows changes. Treat registry, services, AppX removal, package manager, Windows Update, ISO, and unattended setup changes as high-risk.
|
||||
- Prefer existing helper functions for WinGet, Chocolatey, registry, services, progress, and UI updates.
|
||||
- Keep tweaks reversible where the schema supports it by including original values or original states.
|
||||
- Never modify a user's original ISO in-place; follow existing copy/mount/export patterns.
|
||||
- Avoid storing credentials, secrets, or machine-specific paths in repo files.
|
||||
- Preserve logging and user feedback patterns for long-running or destructive operations.
|
||||
|
||||
## 7. Surgical Changes
|
||||
|
||||
- Do not improve adjacent code, comments, formatting, imports, or docs unless required.
|
||||
- Do not refactor working code because you are already in the file.
|
||||
- Do not delete pre-existing dead code unless asked; mention it in the summary if relevant.
|
||||
- Keep diffs reviewable. Every changed line should trace to the user's request.
|
||||
- If a change starts spreading across unrelated areas, pause and reassess the plan.
|
||||
|
||||
## 8. Verification
|
||||
|
||||
Define success in terms that can be checked, then check it.
|
||||
|
||||
- For compile/build changes, run `.\Compile.ps1`.
|
||||
- For GUI behavior changes, run `.\Compile.ps1 -Run` when practical and verify the affected path manually.
|
||||
- For config changes, run the compile check and relevant Pester tests.
|
||||
- For function changes, run the relevant Pester tests or add/update focused tests when practical.
|
||||
- For docs-only changes, proofread the changed files and skip runtime tests unless docs generation is affected.
|
||||
- Read command output. Do not report tests as passing unless they actually passed.
|
||||
- If verification fails, fix the cause rather than weakening the test.
|
||||
|
||||
If a check cannot be run, say exactly why and what residual risk remains.
|
||||
|
||||
## 9. Generated Files And Git Hygiene
|
||||
|
||||
- Treat local `winutil.ps1` changes as disposable compile output.
|
||||
- Never stage or commit `winutil.ps1`, `docs/public/`, `docs/resources/`, `binary/`, editor folders, or other ignored build artifacts.
|
||||
- Do not remove `.gitignore` rules that keep generated artifacts out of Git.
|
||||
- Before finishing, check `git status --short` and separate your changes from pre-existing user changes.
|
||||
- Do not revert user changes unless explicitly asked.
|
||||
- Commit messages, when requested, should be descriptive: short subject under 72 characters, body explaining why when needed.
|
||||
|
||||
## 10. Documentation Expectations
|
||||
|
||||
- Update `docs/content/` when user-facing behavior changes.
|
||||
- Update developer docs when architecture, build flow, config schema, or contribution workflow changes.
|
||||
- Keep README changes brief and high-level.
|
||||
- Put detailed user and developer documentation under `docs/`.
|
||||
- Keep `SPEC.md` aligned with build/runtime contract changes.
|
||||
|
||||
## 11. Communication Style
|
||||
|
||||
- Be direct and concise. Start with the answer or action.
|
||||
- No flattery, filler, ceremonial closings, or fake certainty.
|
||||
- Use bullets only when they improve scanning.
|
||||
- Report what changed, how it was verified, and anything not done.
|
||||
- If the user asks for a review, lead with findings and file/line references.
|
||||
|
||||
## 12. When To Ask
|
||||
|
||||
Ask before proceeding when:
|
||||
|
||||
- The request has two plausible interpretations and the choice materially changes behavior or files touched.
|
||||
- The change affects release generation, generated artifacts, migrations, or high-risk Windows behavior in a way the user did not specify.
|
||||
- You need credentials, secrets, production resources, or access you do not have.
|
||||
- The user's stated goal conflicts with the literal request.
|
||||
|
||||
Proceed without asking when:
|
||||
|
||||
- The task is trivial and reversible.
|
||||
- Ambiguity can be resolved by reading the code or running a local command.
|
||||
- The user already answered the question in this session.
|
||||
|
||||
## 13. Project Learnings
|
||||
|
||||
When the user corrects an agent approach, add or tighten one concrete rule here before ending the session. Keep this section short and prune rules that no longer matter.
|
||||
|
||||
- Keep `winutil.ps1` generated-only: change source files, compile to verify, and never stage the generated script.
|
||||
- Keep WinUtil runtime logging in the existing timestamped `%LocalAppData%\winutil\logs\winutil_*.log` session file; do not create a separate root `winutil.log`.
|
||||
- Import Pester 5.8.0 before running tests so `Invoke-Pester -Output Detailed -CI` does not resolve to Windows' inbox Pester 3.4.0.
|
||||
- Keep package install/uninstall process launches simple unless explicitly requested; do not add a separate stdout/stderr process logging helper for winget or Chocolatey.
|
||||
- When the active log file is owned by `Start-Transcript`, do not call `Add-Content` against that file; write to host output so the transcript captures the line in the same log file without recording a terminating-error diagnostic.
|
||||
- Log install/uninstall package names and package-manager IDs before queuing background runspace work; do not rely on runspace host output for the package identity.
|
||||
- Keep performance tracing helpers under `tools/perf`; include them in generated output only through `Compile.ps1 -Trace`.
|
||||
+40
-3
@@ -1,16 +1,46 @@
|
||||
param (
|
||||
[switch]$Run
|
||||
[switch]$Run,
|
||||
[switch]$Trace
|
||||
)
|
||||
|
||||
$OFS = "`r`n"
|
||||
|
||||
function Get-WinUtilTraceStrippedContent {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Content
|
||||
)
|
||||
|
||||
if ($Trace) {
|
||||
return $Content
|
||||
}
|
||||
|
||||
$filteredLines = $Content -split "`r?`n" | Where-Object {
|
||||
$_ -notmatch '^\s*(Start-WinUtilPerformanceTrace|Stop-WinUtilPerformanceTrace|Write-WinUtilPerformanceCheckpoint)\b'
|
||||
}
|
||||
|
||||
$filteredLines -join "`r`n"
|
||||
}
|
||||
|
||||
# Variable to sync between runspaces
|
||||
$sync = [Hashtable]::Synchronized(@{})
|
||||
$sync.configs = @{}
|
||||
|
||||
$script = (Get-Content -Path scripts\start.ps1) -replace '#{replaceme}', (Get-Date -Format 'yy.MM.dd')
|
||||
|
||||
$script += Get-ChildItem -Path functions -Recurse -File | Get-Content -Raw
|
||||
$script += Get-ChildItem -Path functions -Recurse -File | ForEach-Object {
|
||||
Get-WinUtilTraceStrippedContent -Content (Get-Content -Path $_.FullName -Raw)
|
||||
}
|
||||
|
||||
if ($Trace) {
|
||||
$script += Get-ChildItem -Path tools\perf -Filter *.ps1 -File | Get-Content -Raw
|
||||
|
||||
$script += @'
|
||||
$sync.PerformanceTraceEnabled = $true
|
||||
Start-WinUtilPerformanceTrace
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Config load start"
|
||||
'@
|
||||
}
|
||||
|
||||
Get-ChildItem config | ForEach-Object {
|
||||
$obj = Get-Content -Path $_.FullName -Raw | ConvertFrom-Json
|
||||
@@ -27,6 +57,13 @@ Get-ChildItem config | ForEach-Object {
|
||||
|
||||
$sync.configs[$_.BaseName] = $obj
|
||||
$script += "`$sync.configs.$($_.BaseName) = @'`r`n$json`r`n'@ | ConvertFrom-Json"
|
||||
if ($Trace) {
|
||||
$script += "`r`nWrite-WinUtilPerformanceCheckpoint -Name `"Config $($_.BaseName) loaded`""
|
||||
}
|
||||
}
|
||||
|
||||
if ($Trace) {
|
||||
$script += "`r`nWrite-WinUtilPerformanceCheckpoint -Name `"Config load complete`""
|
||||
}
|
||||
|
||||
$xaml = Get-Content -Path xaml\inputXML.xaml -Raw
|
||||
@@ -35,7 +72,7 @@ $script += "`$inputXML = @'`r`n$xaml`r`n'@"
|
||||
$autounattendXml = Get-Content -Path tools\autounattend.xml -Raw
|
||||
$script += "`$WinUtilAutounattendXml = @'`r`n$autounattendXml`r`n'@"
|
||||
|
||||
$script += Get-Content -Path scripts\main.ps1 -Raw
|
||||
$script += Get-WinUtilTraceStrippedContent -Content (Get-Content -Path scripts\main.ps1 -Raw)
|
||||
|
||||
Set-Content -Path winutil.ps1 -Value $script
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
# SPEC.md
|
||||
|
||||
## Project Contract
|
||||
|
||||
WinUtil is a Windows PowerShell utility with a WPF interface. The repository is maintained as modular source files, but the released artifact is a single generated `winutil.ps1` script.
|
||||
|
||||
The compiled `winutil.ps1` is not source code for editing or review. It is generated by `Compile.ps1` and produced during release automation. All durable changes must be made to the source files that feed the compiler.
|
||||
|
||||
## Goals
|
||||
|
||||
- Provide a single-script Windows utility that can be launched from PowerShell.
|
||||
- Keep development modular enough for contributors to work on functions, config, UI, docs, and tooling independently.
|
||||
- Make install, tweak, feature, repair, update, and ISO workflows discoverable from the WPF UI.
|
||||
- Keep common lists and options declarative in JSON config where possible.
|
||||
- Preserve a repeatable compile process so local builds and GitHub Actions builds produce the distributable script from the same inputs.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- `winutil.ps1` is not hand-maintained.
|
||||
- The project is not structured as a PowerShell module at runtime.
|
||||
- The GUI is not a separate packaged desktop application in this repository's normal release path.
|
||||
- Generated files should not be reviewed as source changes.
|
||||
|
||||
## Repository Layout
|
||||
|
||||
- `Compile.ps1`: build script that creates `winutil.ps1`.
|
||||
- `scripts/start.ps1`: startup/bootstrap segment used at the beginning of the compiled script.
|
||||
- `scripts/main.ps1`: main entrypoint appended at the end of the compiled script.
|
||||
- `functions/public/`: public/UI-facing PowerShell functions.
|
||||
- `functions/private/`: internal helper PowerShell functions.
|
||||
- `config/`: JSON configuration consumed at compile time and embedded into `$sync.configs`.
|
||||
- `xaml/inputXML.xaml`: WPF UI markup embedded into the compiled script.
|
||||
- `tools/autounattend.xml`: unattended setup XML embedded for Windows ISO workflows.
|
||||
- `pester/`: Pester tests for config and function checks.
|
||||
- `lint/PSScriptAnalyser.ps1`: PowerShell Script Analyzer settings.
|
||||
- `docs/`: Hugo documentation site.
|
||||
- `winutil.ps1`: ignored generated build artifact.
|
||||
|
||||
## Compile Specification
|
||||
|
||||
`Compile.ps1` must produce a standalone root `winutil.ps1` by combining all required project files.
|
||||
|
||||
The compile flow is:
|
||||
|
||||
1. Initialize shared state with `$sync = [Hashtable]::Synchronized(@{})` and `$sync.configs = @{}`.
|
||||
2. Read `scripts/start.ps1`.
|
||||
3. Replace `#{replaceme}` in startup code with the current `yy.MM.dd` build date.
|
||||
4. Append raw content from all files under `functions/` recursively.
|
||||
5. For every file in `config/`, parse JSON and embed it into `$sync.configs.<basename>`.
|
||||
6. Special-case `config/applications.json` so application keys are emitted with the `WPFInstall` prefix.
|
||||
7. Embed `xaml/inputXML.xaml` as `$inputXML`.
|
||||
8. Embed `tools/autounattend.xml` as `$WinUtilAutounattendXml`.
|
||||
9. Append `scripts/main.ps1`.
|
||||
10. Write the combined script to `winutil.ps1`.
|
||||
11. If `-Run` is supplied, execute the generated script.
|
||||
|
||||
The generated script must have everything it needs from repository sources embedded or appended by this process.
|
||||
|
||||
## Runtime Model
|
||||
|
||||
- WinUtil runs in PowerShell on Windows and uses WPF for the UI.
|
||||
- Shared mutable state is stored in `$sync`, including configs, UI element references, runspace state, selections, and progress.
|
||||
- Long-running operations should use runspaces or existing async patterns so the UI remains responsive.
|
||||
- UI updates from background work must be dispatched back to the WPF UI thread.
|
||||
- Declarative features such as apps, tweaks, presets, DNS providers, and navigation should stay in `config/*.json` unless code is required.
|
||||
|
||||
## UI And Event Contract
|
||||
|
||||
- UI layout lives in `xaml/inputXML.xaml`.
|
||||
- Named WPF controls are discovered and stored in `$sync`.
|
||||
- Button/action wiring follows existing naming conventions, where an element named like `WPFThingButton` maps to a function named like `Invoke-WPFThingButton`.
|
||||
- When adding controls, ensure the XAML name, config key, and PowerShell function names line up with the existing event system.
|
||||
|
||||
## Configuration Contract
|
||||
|
||||
Config files must remain valid JSON and compile cleanly through `ConvertFrom-Json`.
|
||||
|
||||
`config/applications.json` defines installable applications. Each application entry should include the fields expected by tests and UI code, such as package manager IDs, category, display content, description, and link.
|
||||
|
||||
`config/tweaks.json` defines Windows tweaks. Registry and service changes should include original values or original states when applicable so undo workflows can restore user systems.
|
||||
|
||||
Preset and navigation files should reference valid config keys. Avoid renaming config keys unless all presets, UI references, docs, and code paths are updated together.
|
||||
|
||||
## Safety Requirements
|
||||
|
||||
- Registry, service, package manager, Windows Update, AppX removal, and ISO operations can affect the host system. Changes must be explicit, reversible where practical, and consistent with existing logging and confirmation patterns.
|
||||
- Tweak changes should include undo metadata when the schema supports it.
|
||||
- Package installation should prefer existing WinGet and Chocolatey helper functions.
|
||||
- ISO workflows must not modify the user's original ISO file; they should work on copied/mounted content following existing patterns.
|
||||
|
||||
## Testing And CI
|
||||
|
||||
Expected validation for source changes:
|
||||
|
||||
- `.\Compile.ps1` verifies the compiler can generate `winutil.ps1`.
|
||||
- `.\Compile.ps1 -Run` compiles and launches the generated utility for manual GUI verification.
|
||||
- `Install-Module -Name Pester -RequiredVersion 5.8.0 -Scope CurrentUser -Force -SkipPublisherCheck` installs the supported Pester version.
|
||||
- `Import-Module Pester -RequiredVersion 5.8.0 -Force; Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed -CI` runs the Pester suite.
|
||||
- GitHub Actions also runs a compile check and PowerShell Script Analyzer with `lint/PSScriptAnalyser.ps1`.
|
||||
|
||||
The generated `winutil.ps1` may appear locally after compile. It remains ignored build output and must not be committed.
|
||||
|
||||
## Release Artifact
|
||||
|
||||
GitHub Actions is responsible for producing the release `winutil.ps1` from repository sources. A release should be considered valid only if the generated script came from the compile process, not from direct manual edits to `winutil.ps1`.
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
# Test TODO
|
||||
|
||||
Current suite status: broad parser, import, config JSON, compile, and runspace smoke coverage exists, but runtime behavior coverage is still very thin. Work from the top down; the first items are the highest-value gaps.
|
||||
|
||||
## P0 - Highest Priority
|
||||
|
||||
- [x] Add config reference integrity tests.
|
||||
- Verify every preset entry points to an existing tweak, feature, app, appx item, or supported action.
|
||||
- Verify `appnavigation.json` entries point to real tabs/panels and valid config groups.
|
||||
- Verify tweak, feature, DNS, appx, and theme entries include all fields used by the UI/rendering code.
|
||||
- Verify all embedded script strings in `config/*.json` parse as PowerShell when wrapped as scriptblocks.
|
||||
|
||||
- [x] Add XAML/control wiring tests.
|
||||
- Load `xaml/inputXML.xaml` as XML and verify expected named controls exist.
|
||||
- Verify controls referenced through `$sync["Name"]`, `$sync.Name`, or event handlers exist in XAML or are intentionally created dynamically.
|
||||
- Verify `Invoke-WPF*` handler names used by buttons/tabs correspond to real functions.
|
||||
- Verify core tabs, search controls, install panels, tweak panels, and Win11 Creator controls are present.
|
||||
|
||||
- [x] Add mock-based tests for registry and service helpers.
|
||||
- Cover `Set-WinUtilRegistry` set/remove paths with `Mock New-Item`, `Mock Set-ItemProperty`, and `Mock Remove-ItemProperty`.
|
||||
- Cover `Set-WinUtilService` for missing services, startup type changes, and no-op behavior.
|
||||
- Assert command parameters instead of touching the real registry or services.
|
||||
|
||||
- [x] Add package selection and package manager tests.
|
||||
- Cover `Get-WinUtilSelectedPackages` for winget-only, choco-only, mixed, `na`, empty, duplicate, and missing package entries.
|
||||
- Cover `Test-WinUtilPackageManager` with mocked `Get-Command`.
|
||||
- Cover `Install-WinUtilProgramWinget` and `Install-WinUtilProgramChoco` with mocked `Start-Process`, including install/uninstall arguments.
|
||||
|
||||
- [x] Add runspace behavior tests beyond the smoke test.
|
||||
- Cover no argument list, one named parameter, multiple named parameters, and scriptblock failures.
|
||||
- Assert callers receive a single `IAsyncResult`.
|
||||
- Verify failure output/errors can be retrieved by the owning PowerShell instance.
|
||||
- Add focused tests for public functions that call `Invoke-WPFRunspace` without executing their destructive inner work.
|
||||
|
||||
## P1 - Important Workflow Coverage
|
||||
|
||||
- [x] Add tweak execution orchestration tests.
|
||||
- Cover `Invoke-WinUtilTweaks` with mocked `Invoke-WinUtilScript`, `Set-WinUtilRegistry`, `Set-WinUtilService`, and `Set-WinUtilDNS`.
|
||||
- Verify undo mode uses `OriginalValue` and `OriginalType`.
|
||||
- Verify DNS provider and progress counters are passed through correctly.
|
||||
|
||||
- [x] Add install/uninstall workflow tests.
|
||||
- Cover `Invoke-WPFInstall` and `Invoke-WPFUnInstall` with mocked package sorting and mocked installers.
|
||||
- Verify empty selection prompts and exits.
|
||||
- Verify process-running guard prevents a second install/uninstall.
|
||||
- Verify taskbar/progress cleanup happens on success and error.
|
||||
|
||||
- [x] Add update profile tests.
|
||||
- Cover `Invoke-WPFUpdatesdisable`, `Invoke-WPFUpdatesdefault`, and `Invoke-WPFUpdatessecurity` with mocks for registry, services, scheduled tasks, and process calls.
|
||||
- Assert intended registry paths, values, service startup types, and scheduled task paths.
|
||||
- Keep all tests non-mutating.
|
||||
|
||||
- [x] Add AppX removal tests.
|
||||
- Cover `Remove-WinUtilAPPX` with mocked `Get-AppxPackage` and `Remove-AppxPackage`.
|
||||
- Cover `Invoke-WPFAppxRemoval` selection behavior and runspace parameter passing.
|
||||
- Verify empty selection is handled without removal calls.
|
||||
|
||||
- [x] Add UI selection/state helper tests.
|
||||
- Cover `Update-WinUtilSelections`, `Reset-WPFCheckBoxes`, `Invoke-WPFSelectedCheckboxesUpdate`, and `Invoke-WPFToggleAllCategories`.
|
||||
- Use small fake checkbox/control objects instead of WPF windows where possible.
|
||||
- Verify selected apps, tweaks, toggles, appx, and features stay in sync with checkbox state.
|
||||
|
||||
## P2 - Domain-Specific Coverage
|
||||
|
||||
- [x] Expand Win11 Creator tests.
|
||||
- Test edition name to edition ID mapping.
|
||||
- Test `ei.cfg` and `PID.txt` generation/removal behavior in a temp directory.
|
||||
- Test autounattend conversion preserves required nodes and removes unsupported product key paths.
|
||||
- Test driver injection branching with mocked DISM commands.
|
||||
- Test ISO export fallback when `oscdimg.exe` is missing and winget install fails.
|
||||
|
||||
- [x] Add preferences/theme tests.
|
||||
- Cover `Set-Preferences` loading, saving, old preference cleanup, and defaults.
|
||||
- Cover theme resource updates without opening the full GUI.
|
||||
- Verify theme config contains required brushes/colors used by the theme code.
|
||||
|
||||
- [x] Add search/filter tests.
|
||||
- Cover `Find-AppsByNameOrDescription` and `Find-TweaksByNameOrDescription` with fake UI item trees.
|
||||
- Verify empty search restores visibility.
|
||||
- Verify category labels and panels hide/show correctly.
|
||||
- Verify description and display-name matches both work.
|
||||
|
||||
- [x] Add compile contract tests.
|
||||
- Verify compiled config key transformation for `applications.json` adds `WPFInstall` prefixes.
|
||||
- Verify source ordering in `winutil.ps1`: start script, functions, configs, XAML, autounattend XML, main script.
|
||||
- Verify generated build date placeholder is replaced.
|
||||
- Verify generated script does not contain unresolved `#{replaceme}`.
|
||||
|
||||
## P3 - Nice To Have
|
||||
|
||||
- [ ] Add Script Analyzer as a failing CI gate once existing findings are triaged.
|
||||
- [ ] Add docs generation/link checks for `docs/content`.
|
||||
- [ ] Add coverage reporting in CI as informational output.
|
||||
- [ ] Add a lightweight test helper module for fake `$sync`, fake WPF controls, and common mocks.
|
||||
- [ ] Add regression tests whenever a production bug is fixed.
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Tests must not mutate the real registry, services, scheduled tasks, package managers, AppX packages, USB disks, ISOs, or user profile state.
|
||||
- Prefer Pester mocks and temp directories for system-facing code.
|
||||
- Keep generated `winutil.ps1` ignored and never commit it.
|
||||
- Run the full gate before marking test work complete:
|
||||
|
||||
```powershell
|
||||
Import-Module Pester -RequiredVersion 5.8.0 -Force
|
||||
Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed -CI
|
||||
```
|
||||
@@ -161,6 +161,15 @@
|
||||
"winget": "Cemu.Cemu",
|
||||
"foss": true
|
||||
},
|
||||
"chatgpt": {
|
||||
"category": "Development",
|
||||
"choco": "na",
|
||||
"content": "ChatGPT Desktop",
|
||||
"description": "The official ChatGPT desktop app for Windows, distributed through the Microsoft Store.",
|
||||
"link": "https://apps.microsoft.com/detail/9nt1r1c2hh7j",
|
||||
"winget": "msstore:9NT1R1C2HH7J",
|
||||
"foss": false
|
||||
},
|
||||
"chatterino": {
|
||||
"category": "Communications",
|
||||
"choco": "chatterino",
|
||||
@@ -188,6 +197,33 @@
|
||||
"winget": "Hibbiki.Chromium",
|
||||
"foss": true
|
||||
},
|
||||
"cinebenchr23": {
|
||||
"category": "Pro Tools",
|
||||
"choco": "na",
|
||||
"content": "Cinebench R23",
|
||||
"description": "Cinebench R23 is a benchmark tool for comparing CPU rendering performance across systems.",
|
||||
"link": "https://www.maxon.net/en/cinebench",
|
||||
"winget": "Maxon.CinebenchR23",
|
||||
"foss": false
|
||||
},
|
||||
"claude": {
|
||||
"category": "Development",
|
||||
"choco": "claude",
|
||||
"content": "Claude Desktop",
|
||||
"description": "Anthropic's Claude desktop application for focused AI-assisted work and chat.",
|
||||
"link": "https://claude.ai/download",
|
||||
"winget": "Anthropic.Claude",
|
||||
"foss": false
|
||||
},
|
||||
"claude-code": {
|
||||
"category": "Development",
|
||||
"choco": "claude-code",
|
||||
"content": "Claude Code",
|
||||
"description": "Anthropic's agentic coding tool for terminal and IDE development workflows.",
|
||||
"link": "https://code.claude.com/",
|
||||
"winget": "Anthropic.ClaudeCode",
|
||||
"foss": false
|
||||
},
|
||||
"cmake": {
|
||||
"category": "Development",
|
||||
"choco": "cmake",
|
||||
@@ -197,6 +233,15 @@
|
||||
"winget": "Kitware.CMake",
|
||||
"foss": true
|
||||
},
|
||||
"codex": {
|
||||
"category": "Development",
|
||||
"choco": "codex",
|
||||
"content": "Codex",
|
||||
"description": "Codex CLI is an OpenAI coding agent that runs locally in your terminal.",
|
||||
"link": "https://developers.openai.com/codex/cli",
|
||||
"winget": "OpenAI.Codex",
|
||||
"foss": true
|
||||
},
|
||||
"cpuz": {
|
||||
"category": "Pro Tools",
|
||||
"choco": "cpu-z",
|
||||
@@ -314,6 +359,15 @@
|
||||
"winget": "Microsoft.DotNet.DesktopRuntime.10",
|
||||
"foss": true
|
||||
},
|
||||
"dropbox": {
|
||||
"category": "Utilities",
|
||||
"choco": "dropbox",
|
||||
"content": "Dropbox",
|
||||
"description": "Dropbox is a cloud storage client for syncing files, sharing content, and keeping documents available across devices.",
|
||||
"link": "https://www.dropbox.com/desktop",
|
||||
"winget": "Dropbox.Dropbox",
|
||||
"foss": false
|
||||
},
|
||||
"eaapp": {
|
||||
"category": "Games",
|
||||
"choco": "ea-app",
|
||||
@@ -539,6 +593,15 @@
|
||||
"winget": "DuongDieuPhap.ImageGlass",
|
||||
"foss": true
|
||||
},
|
||||
"internetdownloadmanager": {
|
||||
"category": "Utilities",
|
||||
"choco": "internet-download-manager",
|
||||
"content": "Internet Download Manager",
|
||||
"description": "Internet Download Manager is a download manager for accelerating, resuming, and scheduling file downloads.",
|
||||
"link": "https://www.internetdownloadmanager.com/",
|
||||
"winget": "Tonec.InternetDownloadManager",
|
||||
"foss": false
|
||||
},
|
||||
"irfanview": {
|
||||
"category": "Multimedia Tools",
|
||||
"choco": "irfanview",
|
||||
@@ -1285,6 +1348,15 @@
|
||||
"winget": "SlackTechnologies.Slack",
|
||||
"foss": false
|
||||
},
|
||||
"startallback": {
|
||||
"category": "Utilities",
|
||||
"choco": "StartAllBack",
|
||||
"content": "StartAllBack",
|
||||
"description": "StartAllBack restores and improves Windows taskbar, Start menu, File Explorer, and shell UI behavior.",
|
||||
"link": "https://www.startallback.com/",
|
||||
"winget": "StartIsBack.StartAllBack",
|
||||
"foss": false
|
||||
},
|
||||
"steam": {
|
||||
"category": "Games",
|
||||
"choco": "steam-client",
|
||||
@@ -1573,6 +1645,15 @@
|
||||
"winget": "Waterfox.Waterfox",
|
||||
"foss": true
|
||||
},
|
||||
"whatsapp": {
|
||||
"category": "Communications",
|
||||
"choco": "na",
|
||||
"content": "WhatsApp Desktop",
|
||||
"description": "WhatsApp Desktop is the official Windows desktop messaging app from Meta, distributed through the Microsoft Store.",
|
||||
"link": "https://apps.microsoft.com/detail/9nksqgp7f2nh",
|
||||
"winget": "msstore:9NKSQGP7F2NH",
|
||||
"foss": false
|
||||
},
|
||||
"wingetui": {
|
||||
"category": "Utilities",
|
||||
"choco": "wingetui",
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
{
|
||||
"WPFAppxMicrosoft_WindowsFeedbackHub": {
|
||||
"Category": "Microsoft Apps",
|
||||
"Content": "Feedback Hub",
|
||||
"Description": "Allows users to submit bug reports, feature suggestions, and diagnostic data directly to Microsoft.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.WindowsFeedbackHub"
|
||||
},
|
||||
"WPFAppxMicrosoft_GetHelp": {
|
||||
"Category": "Microsoft Apps",
|
||||
"Content": "Get Help",
|
||||
"Description": "Provides access to automated troubleshooting guides, support documentation, and direct Microsoft customer assistance.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.GetHelp"
|
||||
},
|
||||
"WPFAppxMicrosoft_OutlookForWindows": {
|
||||
"Category": "Microsoft Apps",
|
||||
"Content": "Outlook for Windows",
|
||||
"Description": "Provides modern email management, calendar scheduling, and contact organization features.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.OutlookForWindows"
|
||||
},
|
||||
"WPFAppxMSTeams": {
|
||||
"Category": "Microsoft Apps",
|
||||
"Content": "Microsoft Teams",
|
||||
"Description": "Facilitates instant messaging, video conferencing, file sharing, and workspace collaboration.",
|
||||
"Panel": "0",
|
||||
"PackageId": "MSTeams"
|
||||
},
|
||||
"WPFAppxClipchamp_Clipchamp": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Clipchamp",
|
||||
"Description": "Provides a user-friendly video editor with built-in templates, effects, and timeline editing tools.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Clipchamp.Clipchamp"
|
||||
},
|
||||
"WPFAppxMicrosoft_MicrosoftOfficeHub": {
|
||||
"Category": "Microsoft Apps",
|
||||
"Content": "Microsoft 365",
|
||||
"Description": "Serves as a centralized launcher and dashboard for accessing cloud-based Microsoft 365 apps and recent documents.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.MicrosoftOfficeHub"
|
||||
},
|
||||
"WPFAppxMicrosoft_ZuneMusic": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Media Player",
|
||||
"Description": "Plays local audio and video files with modern playlist management and casting capabilities.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.ZuneMusic"
|
||||
},
|
||||
"WPFAppxMicrosoft_BingSearch": {
|
||||
"Category": "Bing & Web Services",
|
||||
"Content": "Bing Search",
|
||||
"Description": "Integrates Microsoft Bing search capabilities and web services directly into the operating system.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.BingSearch"
|
||||
},
|
||||
"WPFAppxMicrosoftCorporationII_QuickAssist": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Quick Assist",
|
||||
"Description": "Enables secure remote technical support and screen sharing over an internet connection.",
|
||||
"Panel": "0",
|
||||
"PackageId": "MicrosoftCorporationII.QuickAssist"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsDevHome": {
|
||||
"Category": "Developer Tools",
|
||||
"Content": "Dev Home",
|
||||
"Description": "Provides a specialized dashboard for software developer environment setups, repository syncing, and hardware widgets.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.Windows.DevHome"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsCrossDevice": {
|
||||
"Category": "Microsoft Ecosystem",
|
||||
"Content": "Mobile Devices",
|
||||
"Description": "Manages system-level background connectivity with paired mobile devices. Removing this may disable cross-device features such as phone screen mirroring, file transfer, and mobile hotspot handoff integrated into Windows Settings.",
|
||||
"Panel": "0",
|
||||
"PackageId": "MicrosoftWindows.CrossDevice"
|
||||
},
|
||||
"WPFAppxMicrosoft_Todos": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "To Do",
|
||||
"Description": "Creates, tracks, and synchronizes personal tasks, smart lists, and daily reminders.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.Todos"
|
||||
},
|
||||
"WPFAppxMicrosoft_PowerAutomateDesktop": {
|
||||
"Category": "Developer Tools",
|
||||
"Content": "Power Automate",
|
||||
"Description": "Automates repetitive workflows and desktop tasks using low-code visual scripting.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.PowerAutomateDesktop"
|
||||
},
|
||||
"WPFAppxMicrosoft_YourPhone": {
|
||||
"Category": "Microsoft Ecosystem",
|
||||
"Content": "Phone Link",
|
||||
"Description": "Synchronizes text messages, phone notifications, photos, and calls from a mobile device to the desktop.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.YourPhone"
|
||||
},
|
||||
"WPFAppxMicrosoft_MicrosoftStickyNotes": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Sticky Notes",
|
||||
"Description": "Creates quick, floating text notes on the desktop that automatically sync across devices.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.MicrosoftStickyNotes"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsSoundRecorder": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Sound Recorder",
|
||||
"Description": "Records and trims live audio inputs with simple microphone adjustment controls.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.WindowsSoundRecorder"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsAlarms": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Clock",
|
||||
"Description": "Features world clocks, alarms, countdown timers, stopwatches, and dedicated focus session tracking.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.WindowsAlarms"
|
||||
},
|
||||
"WPFAppxMicrosoft_Paint": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Paint",
|
||||
"Description": "Provides built-in digital sketching, basic image editing, and pixel-level graphic manipulation tools.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.Paint"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsNotepad": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Notepad",
|
||||
"Description": "Provides a lightweight text editor with multi-tab support for plain text files and code snippets.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.WindowsNotepad"
|
||||
},
|
||||
"WPFAppxMicrosoft_ScreenSketch": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Snipping Tool",
|
||||
"Description": "Captures screenshots or screen recordings with built-in markup, image cropping, and optical character recognition (OCR).",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.ScreenSketch"
|
||||
},
|
||||
"WPFAppxMicrosoft_Copilot": {
|
||||
"Category": "Bing & Web Services",
|
||||
"Content": "Copilot",
|
||||
"Description": "Launches the Microsoft AI companion for contextual answers, creative writing assistance, and intelligent web search.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.Copilot"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsCalculator": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Calculator",
|
||||
"Description": "Performs standard arithmetic, scientific operations, programming calculations, and unit conversions.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.WindowsCalculator"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsCamera": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Camera",
|
||||
"Description": "Captures photographs and records video files via connected webcams or imaging hardware.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.WindowsCamera"
|
||||
},
|
||||
"WPFAppxMicrosoft_WindowsPhotos": {
|
||||
"Category": "Utilities & Productivity",
|
||||
"Content": "Photos",
|
||||
"Description": "Organizes, views, and crops local images with basic color adjustment and album creation tools.",
|
||||
"Panel": "0",
|
||||
"PackageId": "Microsoft.Windows.Photos"
|
||||
},
|
||||
"WPFAppxMicrosoft_BingNews": {
|
||||
"Category": "Bing & Web Services",
|
||||
"Content": "News",
|
||||
"Description": "Aggregates breaking news headlines, personalized article feeds, and world current events.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.BingNews"
|
||||
},
|
||||
"WPFAppxMicrosoft_BingWeather": {
|
||||
"Category": "Bing & Web Services",
|
||||
"Content": "Weather",
|
||||
"Description": "Displays local real-time weather tracking, radar maps, and historical meteorological forecasts.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.BingWeather"
|
||||
},
|
||||
"WPFAppxMicrosoft_GamingApp": {
|
||||
"Category": "Xbox & Gaming",
|
||||
"Content": "Xbox App",
|
||||
"Description": "Serves as the primary gaming library manager, social community interface, and PC Game Pass dashboard.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.GamingApp"
|
||||
},
|
||||
"WPFAppxMicrosoft_XboxGamingOverlay": {
|
||||
"Category": "Xbox & Gaming",
|
||||
"Content": "Xbox Game Bar",
|
||||
"Description": "Provides customizable in-game status widgets, audio balancing sliders, system monitoring tools, and gameplay recording.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.XboxGamingOverlay"
|
||||
},
|
||||
"WPFAppxMicrosoft_XboxIdentityProvider": {
|
||||
"Category": "Xbox & Gaming",
|
||||
"Content": "Xbox Identity Provider",
|
||||
"Description": "Manages Xbox network user authentication and background account validation for connected titles. Warning: removing this may break Microsoft account sign-in for non-Xbox games and apps that rely on this authentication pipeline.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.XboxIdentityProvider"
|
||||
},
|
||||
"WPFAppxMicrosoft_XboxSpeechToTextOverlay": {
|
||||
"Category": "Xbox & Gaming",
|
||||
"Content": "Xbox Speech To Text Overlay",
|
||||
"Description": "Provides system-level live accessibility captions and voice-to-text translation for gaming chat networks.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.XboxSpeechToTextOverlay"
|
||||
},
|
||||
"WPFAppxMicrosoft_Xbox_TCUI": {
|
||||
"Category": "Xbox & Gaming",
|
||||
"Content": "Xbox TCUI",
|
||||
"Description": "Provides core account connection UI modules for single sign-on flows within game titles. Warning: removing this may break Microsoft account authentication in games and apps that do not otherwise require the Xbox app.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.Xbox.TCUI"
|
||||
},
|
||||
"WPFAppxMicrosoft_StartExperiencesApp": {
|
||||
"Category": "Bing & Web Services",
|
||||
"Content": "Start Experiences App",
|
||||
"Description": "Powers the Windows Widgets board, delivering a personalized feed of news, weather, sports, and finance content.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.StartExperiencesApp"
|
||||
},
|
||||
"WPFAppxMicrosoft_MicrosoftSolitaireCollection": {
|
||||
"Category": "Xbox & Gaming",
|
||||
"Content": "Solitaire Collection",
|
||||
"Description": "Bundles built-in card game modes including Klondike, Spider, FreeCell, Pyramid, and TriPeaks alongside daily challenges.",
|
||||
"Panel": "1",
|
||||
"PackageId": "Microsoft.MicrosoftSolitaireCollection"
|
||||
}
|
||||
}
|
||||
+21
-3
@@ -4,7 +4,6 @@
|
||||
"WPFTweaksConsumerFeatures",
|
||||
"WPFTweaksDisableExplorerAutoDiscovery",
|
||||
"WPFTweaksWPBT",
|
||||
"WPFTweaksDeBloat",
|
||||
"WPFTweaksLocation",
|
||||
"WPFTweaksServices",
|
||||
"WPFTweaksTelemetry",
|
||||
@@ -16,17 +15,16 @@
|
||||
],
|
||||
"Minimal": [
|
||||
"WPFTweaksConsumerFeatures",
|
||||
"WPFTweaksDeBloat",
|
||||
"WPFTweaksWPBT",
|
||||
"WPFTweaksServices",
|
||||
"WPFTweaksTelemetry"
|
||||
],
|
||||
"Advanced": [
|
||||
"WPFTweaksRestorePoint",
|
||||
"WPFTweaksActivity",
|
||||
"WPFTweaksConsumerFeatures",
|
||||
"WPFTweaksDisableExplorerAutoDiscovery",
|
||||
"WPFTweaksWPBT",
|
||||
"WPFTweaksDeBloat",
|
||||
"WPFTweaksLocation",
|
||||
"WPFTweaksServices",
|
||||
"WPFTweaksTelemetry",
|
||||
@@ -39,5 +37,25 @@
|
||||
"WPFTweaksRemoveOneDrive",
|
||||
"WPFTweaksWindowsAI",
|
||||
"WPFTweaksRightClickMenu"
|
||||
],
|
||||
"AppxDefault": [
|
||||
"WPFAppxMicrosoft_WindowsFeedbackHub",
|
||||
"WPFAppxMicrosoft_GetHelp",
|
||||
"WPFAppxMicrosoft_MicrosoftOfficeHub",
|
||||
"WPFAppxMicrosoft_WindowsCalculator",
|
||||
"WPFAppxClipchamp_Clipchamp",
|
||||
"WPFAppxMicrosoft_WindowsAlarms",
|
||||
"WPFAppxMicrosoftCorporationII_QuickAssist",
|
||||
"WPFAppxMicrosoft_WindowsSoundRecorder",
|
||||
"WPFAppxMicrosoft_MicrosoftStickyNotes",
|
||||
"WPFAppxMicrosoft_Todos",
|
||||
"WPFAppxMicrosoft_MicrosoftSolitaireCollection",
|
||||
"WPFAppxMicrosoft_PowerAutomateDesktop",
|
||||
"WPFAppxMicrosoft_WindowsDevHome",
|
||||
"WPFAppxMicrosoft_BingWeather",
|
||||
"WPFAppxMicrosoft_StartExperiencesApp",
|
||||
"WPFAppxMicrosoft_BingNews",
|
||||
"WPFAppxMicrosoft_Copilot",
|
||||
"WPFAppxMicrosoft_BingSearch"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -65,11 +65,13 @@
|
||||
"ButtonConfigBackgroundColor": "#F7F7F7",
|
||||
"ButtonUpdatesBackgroundColor": "#F7F7F7",
|
||||
"ButtonWin11ISOBackgroundColor": "#F7F7F7",
|
||||
"ButtonAppxBackgroundColor": "#F7F7F7",
|
||||
"ButtonInstallForegroundColor": "#232629",
|
||||
"ButtonTweaksForegroundColor": "#232629",
|
||||
"ButtonConfigForegroundColor": "#232629",
|
||||
"ButtonUpdatesForegroundColor": "#232629",
|
||||
"ButtonWin11ISOForegroundColor": "#232629",
|
||||
"ButtonAppxForegroundColor": "#232629",
|
||||
"ButtonBackgroundColor": "#F5F5F5",
|
||||
"ButtonBackgroundPressedColor": "#1A1A1A",
|
||||
"ButtonBackgroundMouseoverColor": "#C2C2C2",
|
||||
@@ -105,11 +107,13 @@
|
||||
"ButtonConfigBackgroundColor": "#444444",
|
||||
"ButtonUpdatesBackgroundColor": "#555555",
|
||||
"ButtonWin11ISOBackgroundColor": "#666666",
|
||||
"ButtonAppxBackgroundColor": "#777777",
|
||||
"ButtonInstallForegroundColor": "#F7F7F7",
|
||||
"ButtonTweaksForegroundColor": "#F7F7F7",
|
||||
"ButtonConfigForegroundColor": "#F7F7F7",
|
||||
"ButtonUpdatesForegroundColor": "#F7F7F7",
|
||||
"ButtonWin11ISOForegroundColor": "#F7F7F7",
|
||||
"ButtonAppxForegroundColor": "#F7F7F7",
|
||||
"ButtonBackgroundColor": "#1E3747",
|
||||
"ButtonBackgroundPressedColor": "#F7F7F7",
|
||||
"ButtonBackgroundMouseoverColor": "#3B4252",
|
||||
|
||||
+22
-74
@@ -91,8 +91,7 @@
|
||||
"OriginalValue": "<RemoveEntry>"
|
||||
}
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/revertstartmenu",
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/revertstartmenu"
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/revertstartmenu"
|
||||
},
|
||||
"WPFTweaksDisableStoreSearch": {
|
||||
"Content": "Microsoft Store Recommended Search Results - Disable",
|
||||
@@ -587,15 +586,25 @@
|
||||
},
|
||||
"WPFTweaksRemoveEdge": {
|
||||
"Content": "Microsoft Edge - Remove",
|
||||
"Description": "Unblocks Microsoft Edge uninstaller restrictions then uses that uninstaller to remove Microsoft Edge.",
|
||||
"Description": "Uninstalls Microsoft Edge by creating dummy MicrosoftEdge.exe file in the legacy Edge folder. This tricks Windows into unlocking the official Edge uninstaller allowing for a system-level removal.",
|
||||
"category": "z__Advanced Tweaks - CAUTION",
|
||||
"panel": "1",
|
||||
"InvokeScript": [
|
||||
"Invoke-WinUtilRemoveEdge"
|
||||
"
|
||||
$Path = Resolve-Path -Path \"$Env:ProgramFiles (x86)\\Microsoft\\Edge\\Application\\*\\Installer\\setup.exe\" | Select-Object -Last 1
|
||||
|
||||
if (Test-Path $Path) {
|
||||
New-Item -Path \"$Env:SystemRoot\\SystemApps\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\MicrosoftEdge.exe\" -Force
|
||||
Start-Process -FilePath $Path -ArgumentList \"--uninstall --system-level --force-uninstall --delete-profile\" -Wait
|
||||
Write-Host \"Microsoft Edge was removed\"
|
||||
} else {
|
||||
Write-Host \"Microsoft Edge is not installed\"
|
||||
}
|
||||
"
|
||||
],
|
||||
"UndoScript": [
|
||||
"
|
||||
Write-Host 'Installing Microsoft Edge...'
|
||||
Write-Host \"Installing Microsoft Edge...\"
|
||||
winget install Microsoft.Edge --source winget
|
||||
"
|
||||
],
|
||||
@@ -641,7 +650,7 @@
|
||||
icacls $Env:OneDrive /deny \"Administrators:(D,DC)\"
|
||||
|
||||
Write-Host \"Uninstalling OneDrive...\"
|
||||
Start-Process 'C:\\Windows\\System32\\OneDriveSetup.exe' -ArgumentList '/uninstall' -Wait
|
||||
Start-Process '$Env:SystemRoot\\System32\\OneDriveSetup.exe' -ArgumentList '/uninstall' -Wait
|
||||
|
||||
# Some of OneDrive files use explorer, and OneDrive uses FileCoAuth
|
||||
Write-Host \"Removing leftover OneDrive Files...\"
|
||||
@@ -649,7 +658,7 @@
|
||||
Stop-Process -Name FileCoAuth,Explorer
|
||||
|
||||
Remove-Item \"$Env:LocalAppData\\Microsoft\\OneDrive\" -Recurse -Force
|
||||
Remove-Item \"C:\\ProgramData\\Microsoft OneDrive\" -Recurse -Force
|
||||
Remove-Item \"$Env:ProgramData\\Microsoft OneDrive\" -Recurse -Force
|
||||
|
||||
# Grant back permission to access OneDrive folder
|
||||
icacls $Env:OneDrive /grant \"Administrators:(D,DC)\"
|
||||
@@ -803,70 +812,6 @@
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/display"
|
||||
},
|
||||
"WPFTweaksXboxRemoval": {
|
||||
"Content": "Xbox & Gaming Components - Remove",
|
||||
"Description": "Removes Xbox services, the Xbox app, Game Bar, and related authentication components.",
|
||||
"category": "z__Advanced Tweaks - CAUTION",
|
||||
"panel": "1",
|
||||
"registry": [
|
||||
{
|
||||
"Path": "HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\GameDVR",
|
||||
"Name": "AppCaptureEnabled",
|
||||
"Value": "0",
|
||||
"Type": "DWord",
|
||||
"OriginalValue": "1"
|
||||
}
|
||||
],
|
||||
"appx": [
|
||||
"Microsoft.XboxIdentityProvider",
|
||||
"Microsoft.XboxSpeechToTextOverlay",
|
||||
"Microsoft.GamingApp",
|
||||
"Microsoft.Xbox.TCUI",
|
||||
"Microsoft.XboxGamingOverlay"
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/xboxremoval"
|
||||
},
|
||||
"WPFTweaksDeBloat": {
|
||||
"Content": "Unwanted Pre-Installed Apps - Remove",
|
||||
"Description": "This will remove a bunch of Windows pre-installed applications which most people dont want on their system.",
|
||||
"category": "Essential Tweaks",
|
||||
"panel": "1",
|
||||
"appx": [
|
||||
"Microsoft.WindowsFeedbackHub",
|
||||
"Microsoft.BingNews",
|
||||
"Microsoft.BingSearch",
|
||||
"Microsoft.BingWeather",
|
||||
"Clipchamp.Clipchamp",
|
||||
"Microsoft.Todos",
|
||||
"Microsoft.PowerAutomateDesktop",
|
||||
"Microsoft.MicrosoftSolitaireCollection",
|
||||
"Microsoft.WindowsSoundRecorder",
|
||||
"Microsoft.MicrosoftStickyNotes",
|
||||
"Microsoft.Windows.DevHome",
|
||||
"Microsoft.Paint",
|
||||
"Microsoft.OutlookForWindows",
|
||||
"Microsoft.WindowsAlarms",
|
||||
"Microsoft.StartExperiencesApp",
|
||||
"Microsoft.GetHelp",
|
||||
"Microsoft.ZuneMusic",
|
||||
"MicrosoftCorporationII.QuickAssist",
|
||||
"MSTeams"
|
||||
],
|
||||
"InvokeScript": [
|
||||
"
|
||||
$TeamsPath = \"$Env:LocalAppData\\Microsoft\\Teams\\Update.exe\"
|
||||
|
||||
if (Test-Path $TeamsPath) {
|
||||
Write-Host \"Uninstalling Teams\"
|
||||
Start-Process $TeamsPath -ArgumentList -uninstall -wait
|
||||
|
||||
Write-Host \"Deleting Teams directory\"
|
||||
Remove-Item $TeamsPath -Recurse -Force
|
||||
}
|
||||
"
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/essential-tweaks/debloat"
|
||||
},
|
||||
"WPFTweaksReservedStorage": {
|
||||
"Content": "Disable Reserved Storage",
|
||||
"Description": "Disables Windows Reserved Storage (7-10 GB held for updates/temp files). Recommended only on small drives. Re-enable before major Windows feature updates to avoid installation failures.",
|
||||
@@ -969,7 +914,10 @@
|
||||
|
||||
Get-AppxPackage -AllUsers \"*Copilot*\" | Remove-AppxPackage -AllUsers
|
||||
Get-AppxPackage -AllUsers Microsoft.MicrosoftOfficeHub | Remove-AppxPackage -AllUsers
|
||||
Remove-AppxPackage $Appx
|
||||
|
||||
if ($Appx) {
|
||||
Remove-AppxPackage $Appx
|
||||
}
|
||||
|
||||
Set-Service -Name WSAIFabricSvc -StartupType Disabled
|
||||
Disable-WindowsOptionalFeature -FeatureName Recall -Online -NoRestart
|
||||
@@ -1018,7 +966,7 @@
|
||||
],
|
||||
"InvokeScript": [
|
||||
"
|
||||
$RazerPath = \"C:\\Windows\\Installer\\Razer\"
|
||||
$RazerPath = \"$Env:SystemRoot\\Installer\\Razer\"
|
||||
|
||||
if (Test-Path $RazerPath) {
|
||||
Remove-Item $RazerPath\\* -Recurse -Force
|
||||
@@ -1031,7 +979,7 @@
|
||||
],
|
||||
"UndoScript": [
|
||||
"
|
||||
icacls \"C:\\Windows\\Installer\\Razer\" /remove:d Everyone
|
||||
icacls \"$Env:SystemRoot\\Installer\\Razer\" /remove:d Everyone
|
||||
"
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/z--advanced-tweaks---caution/razerblock"
|
||||
|
||||
@@ -578,7 +578,9 @@ Tests are in `/pester/`:
|
||||
|
||||
Run tests:
|
||||
```powershell
|
||||
Invoke-Pester
|
||||
Install-Module -Name Pester -RequiredVersion 5.8.0 -Scope CurrentUser -Force -SkipPublisherCheck
|
||||
Import-Module Pester -RequiredVersion 5.8.0 -Force
|
||||
Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed -CI
|
||||
```
|
||||
|
||||
## Build Process
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "System Tray Battery Percentage"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1303}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1251}
|
||||
"WPFToggleBatteryPercentage": {
|
||||
"Content": "System Tray Battery Percentage",
|
||||
"Description": "Shows numeric battery percentage next to the battery icon in the system tray.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Start Menu Bing Search"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1638}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1586}
|
||||
"WPFToggleBingSearch": {
|
||||
"Content": "Start Menu Bing Search",
|
||||
"Description": "Toggles Bing web search results in Windows Search.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Dark Theme for Windows"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1321}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1269}
|
||||
"WPFToggleDarkMode": {
|
||||
"Content": "Dark Theme for Windows",
|
||||
"Description": "Dark Mode for the system and applications.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "BSoD Verbose Mode"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1277}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1225}
|
||||
"WPFToggleDetailedBSoD": {
|
||||
"Content": "BSoD Verbose Mode",
|
||||
"Description": "Gives more information when you blue screen.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Lock Screen - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1674}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1622}
|
||||
"WPFTweaksDisableLockscreen": {
|
||||
"Content": "Lock Screen - Disable",
|
||||
"Description": "Skips the lock screen entirely and goes directly to the sign-in screen on boot and wake.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Game Mode"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1817}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1765}
|
||||
"WPFToggleGameMode": {
|
||||
"Content": "Game Mode",
|
||||
"Description": "Toggles Windows prioritizes gaming performance by allocating system resources to games.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "File Explorer Hidden Files"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1391}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1339}
|
||||
"WPFToggleHiddenFiles": {
|
||||
"Content": "File Explorer Hidden Files",
|
||||
"Description": "Reveals hidden files in Explorer.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Settings Home Page"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1620}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1568}
|
||||
"WPFToggleHideSettingsHome": {
|
||||
"Content": "Settings Home Page",
|
||||
"Description": "Toggles the Home Page in the Windows Settings app.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Logon Screen Acrylic Blur"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1656}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1604}
|
||||
"WPFToggleLoginBlur": {
|
||||
"Content": "Logon Screen Acrylic Blur",
|
||||
"Description": "Toggles the acrylic blur effect on login screen background.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Enable Long Paths"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1843}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1791}
|
||||
"WPFToggleLongPaths": {
|
||||
"Content": "Enable Long Paths",
|
||||
"Description": "Toggles support for file paths longer than 260 characters in Explorer.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Mouse Acceleration"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1524}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1472}
|
||||
"WPFToggleMouseAcceleration": {
|
||||
"Content": "Mouse Acceleration",
|
||||
"Description": "Makes it so Cursor movement is affected by the speed of your physical mouse movements.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Multiplane Overlay"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1498}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1446}
|
||||
"WPFToggleMultiplaneOverlay": {
|
||||
"Content": "Multiplane Overlay",
|
||||
"Description": "Multiplane Overlay compose multiple image layers, which can sometimes cause issues with graphics cards.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Microsoft Outlook New Version"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1437}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1385}
|
||||
"WPFToggleNewOutlook": {
|
||||
"Content": "Microsoft Outlook New Version",
|
||||
"Description": "This will ensures the classic Outlook application is used.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Num Lock on Startup"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1558}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1506}
|
||||
"WPFToggleNumLock": {
|
||||
"Content": "Num Lock on Startup",
|
||||
"Description": "Toggle the Num Lock key state when your computer starts.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "S3 Sleep"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1602}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1550}
|
||||
"WPFToggleS3Sleep": {
|
||||
"Content": "S3 Sleep",
|
||||
"Description": "Toggles between Modern Standby and S3 Sleep, which cuts off power to the CPU while continuing to refresh the memory.",
|
||||
|
||||
@@ -3,6 +3,25 @@ title: "Scrollbars Always Visible"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1427}
|
||||
"WPFToggleScrollbars": {
|
||||
"Content": "Scrollbars Always Visible",
|
||||
"Description": "If enabled, scrollbars will always be visible. If disabled, Windows will automatically hide scrollbars when not in use.",
|
||||
"category": "Customize Preferences",
|
||||
"panel": "2",
|
||||
"Type": "Toggle",
|
||||
"registry": [
|
||||
{
|
||||
"Path": "HKCU:\\Control Panel\\Accessibility",
|
||||
"Name": "DynamicScrollbars",
|
||||
"Value": "0",
|
||||
"Type": "DWord",
|
||||
"OriginalValue": "1",
|
||||
"DefaultState": "false",
|
||||
"link": "https://winutil.christitus.com/dev/tweaks/customize-preferences/scrollbars"
|
||||
}
|
||||
],
|
||||
```
|
||||
|
||||
## Registry Changes
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "File Explorer File Extensions"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1363}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1311}
|
||||
"WPFToggleShowExt": {
|
||||
"Content": "File Explorer File Extensions",
|
||||
"Description": "Shows .file extensions in Explorer (.exe, .png, etc.)",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "S0 Sleep Network Connectivity"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1584}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1532}
|
||||
"WPFToggleStandbyFix": {
|
||||
"Content": "S0 Sleep Network Connectivity",
|
||||
"Description": "Toggles network connectivity during S0 Sleep which is low power idle in modern laptops.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Start Menu Recommendations"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1691}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1639}
|
||||
"WPFToggleStartMenuRecommendations": {
|
||||
"Content": "Start Menu Recommendations",
|
||||
"Description": "Toggles the recommendations section in the Start Menu. WARNING: This will also disable Windows Spotlight on your Lock Screen as a side effect.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Sticky Keys"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1735}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1683}
|
||||
"WPFToggleStickyKeys": {
|
||||
"Content": "Sticky Keys",
|
||||
"Description": "Toggles the Sticky Keys, which activate when clicking shift rapidly.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Taskbar Task View Icon"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1799}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1747}
|
||||
"WPFToggleTaskView": {
|
||||
"Content": "Taskbar Task View Icon",
|
||||
"Description": "Toggles the Task View Button in the Taskbar.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Taskbar Centered Icons"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1753}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1701}
|
||||
"WPFToggleTaskbarAlignment": {
|
||||
"Content": "Taskbar Centered Icons",
|
||||
"Description": "Toggles the Taskbar alignment either to the left or center.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Taskbar Search Icon"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1781}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1729}
|
||||
"WPFToggleTaskbarSearch": {
|
||||
"Content": "Taskbar Search Icon",
|
||||
"Description": "Toggles the Search Button on the Taskbar.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Logon Verbose Mode"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1419}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1367}
|
||||
"WPFToggleVerboseLogon": {
|
||||
"Content": "Logon Verbose Mode",
|
||||
"Description": "Show detailed messages during startup/shutdown.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "ConsumerFeatures - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=431}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=430}
|
||||
"WPFTweaksConsumerFeatures": {
|
||||
"Content": "ConsumerFeatures - Disable",
|
||||
"Description": "Windows will not automatically install any games, third-party apps, or application links from the Windows Store for the signed-in user. Some default Apps will be inaccessible (e.g. Phone Link).",
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
title: "Unwanted Pre-Installed Apps - Remove"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=829}
|
||||
"WPFTweaksDeBloat": {
|
||||
"Content": "Unwanted Pre-Installed Apps - Remove",
|
||||
"Description": "This will remove a bunch of Windows pre-installed applications which most people dont want on their system.",
|
||||
"category": "Essential Tweaks",
|
||||
"panel": "1",
|
||||
"appx": [
|
||||
"Microsoft.WindowsFeedbackHub",
|
||||
"Microsoft.BingNews",
|
||||
"Microsoft.BingSearch",
|
||||
"Microsoft.BingWeather",
|
||||
"Clipchamp.Clipchamp",
|
||||
"Microsoft.Todos",
|
||||
"Microsoft.PowerAutomateDesktop",
|
||||
"Microsoft.MicrosoftSolitaireCollection",
|
||||
"Microsoft.WindowsSoundRecorder",
|
||||
"Microsoft.MicrosoftStickyNotes",
|
||||
"Microsoft.Windows.DevHome",
|
||||
"Microsoft.Paint",
|
||||
"Microsoft.OutlookForWindows",
|
||||
"Microsoft.WindowsAlarms",
|
||||
"Microsoft.StartExperiencesApp",
|
||||
"Microsoft.GetHelp",
|
||||
"Microsoft.ZuneMusic",
|
||||
"MicrosoftCorporationII.QuickAssist",
|
||||
"MSTeams"
|
||||
],
|
||||
"InvokeScript": [
|
||||
"
|
||||
$TeamsPath = \"$Env:LocalAppData\\Microsoft\\Teams\\Update.exe\"
|
||||
|
||||
if (Test-Path $TeamsPath) {
|
||||
Write-Host \"Uninstalling Teams\"
|
||||
Start-Process $TeamsPath -ArgumentList -uninstall -wait
|
||||
|
||||
Write-Host \"Deleting Teams directory\"
|
||||
Remove-Item $TeamsPath -Recurse -Force
|
||||
}
|
||||
"
|
||||
],
|
||||
```
|
||||
@@ -3,7 +3,7 @@ title: "Temporary Files - Remove"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1117}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1065}
|
||||
"WPFTweaksDeleteTempFiles": {
|
||||
"Content": "Temporary Files - Remove",
|
||||
"Description": "Erases TEMP Folders.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Delivery Optimization - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=572}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=571}
|
||||
"WPFTweaksDeliveryOptimization": {
|
||||
"Content": "Delivery Optimization - Disable",
|
||||
"Description": "Stops Windows from using your bandwidth to upload updates to other PCs on the internet or local network.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "BitLocker - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=604}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=613}
|
||||
"WPFTweaksDisableBitLocker": {
|
||||
"Content": "BitLocker - Disable",
|
||||
"Description": "Disables BitLocker.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "File Explorer Automatic Folder Discovery - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1222}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1170}
|
||||
"WPFTweaksDisableExplorerAutoDiscovery": {
|
||||
"Content": "File Explorer Automatic Folder Discovery - Disable",
|
||||
"Description": "Windows Explorer automatically tries to guess the type of the folder based on its contents, slowing down the browsing experience. WARNING! Will disable File Explorer grouping.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Microsoft Store Recommended Search Results - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=97}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=96}
|
||||
"WPFTweaksDisableStoreSearch": {
|
||||
"Content": "Microsoft Store Recommended Search Results - Disable",
|
||||
"Description": "Will not display recommended Microsoft Store apps when searching for apps in the Start menu.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Disk Cleanup - Run"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1104}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1052}
|
||||
"WPFTweaksDiskCleanup": {
|
||||
"Content": "Disk Cleanup - Run",
|
||||
"Description": "Runs Disk Cleanup on Drive C: and removes old Windows Updates.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "End Task With Right Click - Enable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=910}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=855}
|
||||
"WPFTweaksEndTaskOnTaskbar": {
|
||||
"Content": "End Task With Right Click - Enable",
|
||||
"Description": "Enables option to end task when right clicking a program in the taskbar.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Location Tracking - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=110}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=109}
|
||||
"WPFTweaksLocation": {
|
||||
"Content": "Location Tracking - Disable",
|
||||
"Description": "Disables Location Tracking.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Restore Point - Create"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=883}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=828}
|
||||
"WPFTweaksRestorePoint": {
|
||||
"Content": "Restore Point - Create",
|
||||
"Description": "Creates a restore point at runtime in case a revert is needed from WinUtil modifications.",
|
||||
|
||||
@@ -3,6 +3,22 @@ title: "Start Menu Previous Layout - Enable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=80}
|
||||
"WPFTweaksRevertStartMenu": {
|
||||
"Content": "Start Menu Previous Layout - Enable",
|
||||
"Description": "Bring back the old Start Menu layout from before the gradual rollout of the new one in 25H2. On newer versions of Windows !!THIS TWEAK WILL NOT WORK!!",
|
||||
"category": "Essential Tweaks",
|
||||
"panel": "1",
|
||||
"registry": [
|
||||
{
|
||||
"Path": "HKLM:\\SYSTEM\\ControlSet001\\Control\\FeatureManagement\\Overrides\\8\\3036241548",
|
||||
"Name": "EnabledState",
|
||||
"Value": "1",
|
||||
"Type": "DWord",
|
||||
"OriginalValue": "<RemoveEntry>"
|
||||
}
|
||||
],
|
||||
```
|
||||
|
||||
## Registry Changes
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Services - Set to Manual"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=147}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=146}
|
||||
"WPFTweaksServices": {
|
||||
"Content": "Services - Set to Manual",
|
||||
"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.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Telemetry - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=447}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=446}
|
||||
"WPFTweaksTelemetry": {
|
||||
"Content": "Telemetry - Disable",
|
||||
"Description": "Disables Microsoft Telemetry.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Windows Platform Binary Table (WPBT) - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=982}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=930}
|
||||
"WPFTweaksWPBT": {
|
||||
"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.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Adobe URL Block List - Enable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1062}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1010}
|
||||
"WPFTweaksBlockAdobeNet": {
|
||||
"Content": "Adobe URL Block List - Enable",
|
||||
"Description": "Reduces user interruptions by selectively blocking connections to Adobe's activation and telemetry servers. Credit: Ruddernation-Designs",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Brave Browser - Debloat"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=187}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=186}
|
||||
"WPFTweaksBraveDebloat": {
|
||||
"Content": "Brave Browser - Debloat",
|
||||
"Description": "Disables various annoyances like Brave Rewards, Leo AI, Crypto Wallet and VPN.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Background Apps - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1190}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1138}
|
||||
"WPFTweaksDisableBGapps": {
|
||||
"Content": "Background Apps - Disable",
|
||||
"Description": "Disables all Microsoft Store apps from running in the background, which has to be done individually since Windows 11.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Fullscreen Optimizations - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1206}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1154}
|
||||
"WPFTweaksDisableFSO": {
|
||||
"Content": "Fullscreen Optimizations - Disable",
|
||||
"Description": "Disables FSO in all applications. NOTE: This will disable Color Management in Exclusive Fullscreen.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "IPv6 - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1168}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1116}
|
||||
"WPFTweaksDisableIPv6": {
|
||||
"Content": "IPv6 - Disable",
|
||||
"Description": "Disables IPv6.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "System Tray Notifications & Calendar - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1039}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=987}
|
||||
"WPFTweaksDisableNotifications": {
|
||||
"Content": "System Tray Notifications & Calendar - Disable",
|
||||
"Description": "Disables all Notifications INCLUDING Calendar.",
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ title: "RDP Unsigned File Warnings - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=280}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=279}
|
||||
"WPFTweaksDisableWarningForUnsignedRdp": {
|
||||
"Content": "RDP Unsigned File Warnings - Disable",
|
||||
"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: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=707}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=716}
|
||||
"WPFTweaksDisplay": {
|
||||
"Content": "Visual Effects - Set to Best Performance",
|
||||
"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: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=303}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=302}
|
||||
"WPFTweaksEdgeDebloat": {
|
||||
"Content": "Microsoft Edge - Debloat",
|
||||
"Description": "Disables various telemetry options, popups, and other annoyances in Edge.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "IPv6 - Set IPv4 as Preferred"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1130}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1078}
|
||||
"WPFTweaksIPv46": {
|
||||
"Content": "IPv6 - Set IPv4 as Preferred",
|
||||
"Description": "Setting the IPv4 preference can have latency and security benefits on private networks where IPv6 is not configured.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Razer Software Auto-Install - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=998}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=946}
|
||||
"WPFTweaksRazerBlock": {
|
||||
"Content": "Razer Software Auto-Install - Disable",
|
||||
"Description": "Blocks ALL Razer Software installations. The hardware works fine without any software.",
|
||||
@@ -27,7 +27,7 @@ description: ""
|
||||
],
|
||||
"InvokeScript": [
|
||||
"
|
||||
$RazerPath = \"C:\\Windows\\Installer\\Razer\"
|
||||
$RazerPath = \"$Env:SystemRoot\\Installer\\Razer\"
|
||||
|
||||
if (Test-Path $RazerPath) {
|
||||
Remove-Item $RazerPath\\* -Recurse -Force
|
||||
@@ -40,7 +40,7 @@ description: ""
|
||||
],
|
||||
"UndoScript": [
|
||||
"
|
||||
icacls \"C:\\Windows\\Installer\\Razer\" /remove:d Everyone
|
||||
icacls \"$Env:SystemRoot\\Installer\\Razer\" /remove:d Everyone
|
||||
"
|
||||
],
|
||||
```
|
||||
|
||||
@@ -3,18 +3,28 @@ title: "Microsoft Edge - Remove"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=588}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=587}
|
||||
"WPFTweaksRemoveEdge": {
|
||||
"Content": "Microsoft Edge - Remove",
|
||||
"Description": "Unblocks Microsoft Edge uninstaller restrictions then uses that uninstaller to remove Microsoft Edge.",
|
||||
"Description": "Uninstalls Microsoft Edge by creating dummy MicrosoftEdge.exe file in the legacy Edge folder. This tricks Windows into unlocking the official Edge uninstaller allowing for a system-level removal.",
|
||||
"category": "z__Advanced Tweaks - CAUTION",
|
||||
"panel": "1",
|
||||
"InvokeScript": [
|
||||
"Invoke-WinUtilRemoveEdge"
|
||||
"
|
||||
$Path = Resolve-Path -Path \"$Env:ProgramFiles (x86)\\Microsoft\\Edge\\Application\\*\\Installer\\setup.exe\" | Select-Object -Last 1
|
||||
|
||||
if (Test-Path $Path) {
|
||||
New-Item -Path \"$Env:SystemRoot\\SystemApps\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\MicrosoftEdge.exe\" -Force
|
||||
Start-Process -FilePath $Path -ArgumentList \"--uninstall --system-level --force-uninstall --delete-profile\" -Wait
|
||||
Write-Host \"Microsoft Edge was removed\"
|
||||
} else {
|
||||
Write-Host \"Microsoft Edge is not installed\"
|
||||
}
|
||||
"
|
||||
],
|
||||
"UndoScript": [
|
||||
"
|
||||
Write-Host 'Installing Microsoft Edge...'
|
||||
Write-Host \"Installing Microsoft Edge...\"
|
||||
winget install Microsoft.Edge --source winget
|
||||
"
|
||||
],
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "File Explorer Home and Gallery - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=677}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=686}
|
||||
"WPFTweaksRemoveHomeAndGallery": {
|
||||
"Content": "File Explorer Home and Gallery - Disable",
|
||||
"Description": "Removes the Home and Gallery from Explorer and sets This PC as default.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Microsoft OneDrive - Remove"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=633}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=642}
|
||||
"WPFTweaksRemoveOneDrive": {
|
||||
"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.",
|
||||
@@ -15,7 +15,7 @@ description: ""
|
||||
icacls $Env:OneDrive /deny \"Administrators:(D,DC)\"
|
||||
|
||||
Write-Host \"Uninstalling OneDrive...\"
|
||||
Start-Process 'C:\\Windows\\System32\\OneDriveSetup.exe' -ArgumentList '/uninstall' -Wait
|
||||
Start-Process '$Env:SystemRoot\\System32\\OneDriveSetup.exe' -ArgumentList '/uninstall' -Wait
|
||||
|
||||
# Some of OneDrive files use explorer, and OneDrive uses FileCoAuth
|
||||
Write-Host \"Removing leftover OneDrive Files...\"
|
||||
@@ -23,7 +23,7 @@ description: ""
|
||||
Stop-Process -Name FileCoAuth,Explorer
|
||||
|
||||
Remove-Item \"$Env:LocalAppData\\Microsoft\\OneDrive\" -Recurse -Force
|
||||
Remove-Item \"C:\\ProgramData\\Microsoft OneDrive\" -Recurse -Force
|
||||
Remove-Item \"$Env:ProgramData\\Microsoft OneDrive\" -Recurse -Force
|
||||
|
||||
# Grant back permission to access OneDrive folder
|
||||
icacls $Env:OneDrive /grant \"Administrators:(D,DC)\"
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Disable Reserved Storage"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=870}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=815}
|
||||
"WPFTweaksReservedStorage": {
|
||||
"Content": "Disable Reserved Storage",
|
||||
"Description": "Disables Windows Reserved Storage (7-10 GB held for updates/temp files). Recommended only on small drives. Re-enable before major Windows feature updates to avoid installation failures.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Right-Click Menu Previous Layout - Enable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1088}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1036}
|
||||
"WPFTweaksRightClickMenu": {
|
||||
"Content": "Right-Click Menu Previous Layout - Enable",
|
||||
"Description": "Restores the classic context menu when right-clicking in File Explorer, replacing the simplified Windows 11 version.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Storage Sense - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=926}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=871}
|
||||
"WPFTweaksStorage": {
|
||||
"Content": "Storage Sense - Disable",
|
||||
"Description": "Storage Sense deletes temp files automatically.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Teredo - Disable"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1146}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1094}
|
||||
"WPFTweaksTeredo": {
|
||||
"Content": "Teredo - Disable",
|
||||
"Description": "Teredo network tunneling is an IPv6 feature that can cause additional latency, but may cause problems with some games.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Date & Time - Set Time to UTC"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=617}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=626}
|
||||
"WPFTweaksUTC": {
|
||||
"Content": "Date & Time - Set Time to UTC",
|
||||
"Description": "Essential for computers that are dual booting. Fixes the time sync with Linux systems.",
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Windows AI - Disable And Remove"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=942}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=887}
|
||||
"WPFTweaksWindowsAI": {
|
||||
"Content": "Windows AI - Disable And Remove",
|
||||
"Description": "Removes and disables all AI features/packages",
|
||||
@@ -34,7 +34,10 @@ description: ""
|
||||
|
||||
Get-AppxPackage -AllUsers \"*Copilot*\" | Remove-AppxPackage -AllUsers
|
||||
Get-AppxPackage -AllUsers Microsoft.MicrosoftOfficeHub | Remove-AppxPackage -AllUsers
|
||||
Remove-AppxPackage $Appx
|
||||
|
||||
if ($Appx) {
|
||||
Remove-AppxPackage $Appx
|
||||
}
|
||||
|
||||
Set-Service -Name WSAIFabricSvc -StartupType Disabled
|
||||
Disable-WindowsOptionalFeature -FeatureName Recall -Online -NoRestart
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
title: "Xbox & Gaming Components - Remove"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=806}
|
||||
"WPFTweaksXboxRemoval": {
|
||||
"Content": "Xbox & Gaming Components - Remove",
|
||||
"Description": "Removes Xbox services, the Xbox app, Game Bar, and related authentication components.",
|
||||
"category": "z__Advanced Tweaks - CAUTION",
|
||||
"panel": "1",
|
||||
"registry": [
|
||||
{
|
||||
"Path": "HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\GameDVR",
|
||||
"Name": "AppCaptureEnabled",
|
||||
"Value": "0",
|
||||
"Type": "DWord",
|
||||
"OriginalValue": "1"
|
||||
}
|
||||
],
|
||||
"appx": [
|
||||
"Microsoft.XboxIdentityProvider",
|
||||
"Microsoft.XboxSpeechToTextOverlay",
|
||||
"Microsoft.GamingApp",
|
||||
"Microsoft.Xbox.TCUI",
|
||||
"Microsoft.XboxGamingOverlay"
|
||||
],
|
||||
```
|
||||
|
||||
## Registry Changes
|
||||
|
||||
Applications and System Components store and retrieve configuration data to modify Windows settings, so we can use the registry to change many settings in one place.
|
||||
|
||||
You can find information about the registry on [Wikipedia](https://en.wikipedia.org/wiki/Windows_Registry) and [Microsoft's Website](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry).
|
||||
@@ -3,7 +3,7 @@ title: "DNS - Set to:"
|
||||
description: ""
|
||||
---
|
||||
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1868}
|
||||
```json {filename="config/tweaks.json",linenos=inline,linenostart=1816}
|
||||
"WPFchangedns": {
|
||||
"Content": "DNS - Set to:",
|
||||
"category": "z__Advanced Tweaks - CAUTION",
|
||||
|
||||
@@ -51,6 +51,7 @@ Click **Run Windows ISO Modification and Creator** to start the customization pr
|
||||
- **Disable BitLocker and device encryption** — removes startup overhead
|
||||
- **Disable Chat icon** — removes chat taskbar button
|
||||
- **Strip unused editions** — keeps only your selected edition, saving 1–2 GB per removed edition
|
||||
- **Pin the selected edition during setup** — writes setup metadata so OEM firmware keys for a different edition do not force the installer down the wrong product-key path
|
||||
- **Clean the component store** — runs DISM cleanup to reclaim another 300–800 MB
|
||||
|
||||
**Privacy & Telemetry Tweaks:**
|
||||
@@ -132,6 +133,7 @@ When you install Windows 11 from your modified ISO:
|
||||
| USB drive not showing up | Plug it in, wait a few seconds, then click **Refresh** |
|
||||
| Modification seems stuck | The WIM dismount step is slow — wait at least 10 minutes before assuming it's frozen |
|
||||
| "Access Denied" error | Make sure WinUtil is running as Administrator |
|
||||
| "Setup has failed to validate the product key" | Recreate the ISO with the latest WinUtil. The creator now removes stale `PID.txt`, writes `sources\ei.cfg`, and pins the selected image in `autounattend.xml` so setup does not use an embedded OEM key for a different edition |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
function Close-WinUtilRunspacePool {
|
||||
if ($null -eq $sync -or -not $sync.ContainsKey("runspace") -or $null -eq $sync.runspace) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if ($sync.runspace.RunspacePoolStateInfo.State -notin @(
|
||||
[System.Management.Automation.Runspaces.RunspacePoolState]::Closed,
|
||||
[System.Management.Automation.Runspaces.RunspacePoolState]::Closing,
|
||||
[System.Management.Automation.Runspaces.RunspacePoolState]::Broken
|
||||
)) {
|
||||
$sync.runspace.Close()
|
||||
}
|
||||
} finally {
|
||||
$sync.runspace.Dispose()
|
||||
$sync.Remove("runspace")
|
||||
}
|
||||
}
|
||||
@@ -46,12 +46,17 @@ function Find-TweaksByNameOrDescription {
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# 2. GET REFERENCE TO TWEAKS PANEL
|
||||
# 2. GET REFERENCE TO TWEAKS OR APPX PANEL
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
$panelName = "tweakspanel"
|
||||
if ($null -ne $Sync.currentTab -and $Sync.currentTab -eq "AppX") {
|
||||
$panelName = "appxpanel"
|
||||
}
|
||||
|
||||
$tweaksPanel = $null
|
||||
try {
|
||||
$tweaksPanel = $Sync.Form.FindName("tweakspanel")
|
||||
$tweaksPanel = $Sync.Form.FindName($panelName)
|
||||
}
|
||||
catch {
|
||||
# Silent return - panel not found or disposed
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
function Get-WinUtilPackageLogSummary {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[object[]]$Packages,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PackageManagers]$Preference
|
||||
)
|
||||
|
||||
@($Packages | ForEach-Object {
|
||||
$package = $_
|
||||
$packageName = @($package.Name, $package.Description, $package.winget, $package.choco) |
|
||||
Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) -and $_ -ne "na" } |
|
||||
Select-Object -First 1
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace([string]$packageName)) {
|
||||
$packageName = "Unknown package"
|
||||
}
|
||||
|
||||
if ($Preference -eq [PackageManagers]::Choco -and -not [string]::IsNullOrWhiteSpace([string]$package.choco) -and $package.choco -ne "na") {
|
||||
"$packageName (choco: $($package.choco))"
|
||||
} elseif (-not [string]::IsNullOrWhiteSpace([string]$package.winget) -and $package.winget -ne "na") {
|
||||
"$packageName (winget: $($package.winget))"
|
||||
} else {
|
||||
"$packageName (no package id)"
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -21,17 +21,32 @@ function Get-WinUtilSelectedPackages {
|
||||
$packages[[PackageManagers]::Winget] = $packagesWinget
|
||||
$packages[[PackageManagers]::Choco] = $packagesChoco
|
||||
|
||||
function Add-PackageId {
|
||||
param(
|
||||
[System.Collections.ArrayList]$Target,
|
||||
$PackageId
|
||||
)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace([string]$PackageId) -or $PackageId -eq "na") {
|
||||
return
|
||||
}
|
||||
|
||||
if (-not $Target.Contains($PackageId)) {
|
||||
$null = $Target.Add($PackageId)
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($package in $PackageList) {
|
||||
switch ($Preference) {
|
||||
"Choco" {
|
||||
if ($package.choco -eq "na") {
|
||||
$null = $packagesWinget.add($package.winget)
|
||||
if ([string]::IsNullOrWhiteSpace([string]$package.choco) -or $package.choco -eq "na") {
|
||||
Add-PackageId -Target $packagesWinget -PackageId $package.winget
|
||||
} else {
|
||||
$null = $packagesChoco.add($package.choco)
|
||||
Add-PackageId -Target $packagesChoco -PackageId $package.choco
|
||||
}
|
||||
}
|
||||
"Winget" {
|
||||
$null = $packagesWinget.add($package.winget)
|
||||
Add-PackageId -Target $packagesWinget -PackageId $package.winget
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,29 +2,39 @@ Function Get-WinUtilToggleStatus ($ToggleSwitch) {
|
||||
|
||||
$ToggleSwitchReg = $sync.configs.tweaks.$ToggleSwitch.registry
|
||||
|
||||
if ($null -eq $sync.ToggleStatusCache) {
|
||||
$sync.ToggleStatusCache = @{}
|
||||
}
|
||||
|
||||
if ($sync.ToggleStatusCache.ContainsKey($ToggleSwitch)) {
|
||||
return [bool]$sync.ToggleStatusCache[$ToggleSwitch]
|
||||
}
|
||||
|
||||
if (-not (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
|
||||
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS | Out-Null
|
||||
}
|
||||
|
||||
foreach ($regentry in $ToggleSwitchReg) {
|
||||
|
||||
if (-not (Test-Path $regentry.Path)) {
|
||||
New-Item -Path $regentry.Path -Force | Out-Null
|
||||
if (Test-Path $regentry.Path) {
|
||||
$regstate = (Get-ItemProperty -Path $regentry.Path).$($regentry.Name)
|
||||
} else {
|
||||
$regstate = $null
|
||||
}
|
||||
|
||||
$regstate = (Get-ItemProperty -Path $regentry.Path).$($regentry.Name)
|
||||
|
||||
if ($null -eq $regstate) {
|
||||
switch ($regentry.DefaultState) {
|
||||
switch ([string]$regentry.DefaultState) {
|
||||
"true" { $regstate = $regentry.Value }
|
||||
"false" { $regstate = $regentry.OriginalValue }
|
||||
}
|
||||
}
|
||||
|
||||
if ($regstate -ne $regentry.Value) {
|
||||
$sync.ToggleStatusCache[$ToggleSwitch] = $false
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
$sync.ToggleStatusCache[$ToggleSwitch] = $true
|
||||
return $true
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ function Initialize-InstallAppEntry {
|
||||
$appKey
|
||||
)
|
||||
|
||||
$app = $sync.configs.applicationsHashtable.$appKey
|
||||
|
||||
# Create the outer Border for the application type
|
||||
$border = New-Object Windows.Controls.Border
|
||||
$border.Style = $sync.Form.Resources.AppEntryBorderStyle
|
||||
$border.Tag = $appKey
|
||||
$border.ToolTip = $Apps.$appKey.description
|
||||
$border.ToolTip = $app.description
|
||||
$border.Add_MouseLeftButtonUp({
|
||||
$childCheckbox = ($this.Child | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0]
|
||||
$childCheckBox.isChecked = -not $childCheckbox.IsChecked
|
||||
@@ -61,10 +63,10 @@ function Initialize-InstallAppEntry {
|
||||
# Create the TextBlock for the application name
|
||||
$appName = New-Object Windows.Controls.TextBlock
|
||||
$appName.Style = $sync.Form.Resources.AppEntryNameStyle
|
||||
$appName.Text = $Apps.$appKey.content
|
||||
$appName.Text = $app.content
|
||||
|
||||
# Add FOSS label after the name if FOSS
|
||||
if ($Apps.$appKey.foss -eq $true) {
|
||||
if ($app.foss -eq $true) {
|
||||
$fossRun = [System.Windows.Documents.Run]::new(" $([char]0x25CF)")
|
||||
$fossRun.Foreground = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(110, 255, 114))
|
||||
$fossRun.FontSize = 11.5
|
||||
@@ -74,10 +76,13 @@ function Initialize-InstallAppEntry {
|
||||
$checkBox.Content = $appName
|
||||
|
||||
# Add accessibility properties to make the elements screen reader friendly
|
||||
$checkBox.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content)
|
||||
$border.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content)
|
||||
$checkBox.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $app.content)
|
||||
$border.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $app.content)
|
||||
|
||||
$border.Child = $checkBox
|
||||
if ($sync.selectedApps -contains $appKey) {
|
||||
$checkBox.IsChecked = $true
|
||||
}
|
||||
# Add the border to the corresponding Category
|
||||
$TargetElement.Children.Add($border) | Out-Null
|
||||
return $checkbox
|
||||
|
||||
@@ -16,7 +16,7 @@ function Initialize-InstallCategoryAppList {
|
||||
$Apps
|
||||
)
|
||||
|
||||
# Pre-group apps by category
|
||||
# Pre-group apps by category before creating WPF controls.
|
||||
$appsByCategory = @{}
|
||||
foreach ($appKey in $Apps.Keys) {
|
||||
$category = $Apps.$appKey.Category
|
||||
@@ -25,6 +25,8 @@ function Initialize-InstallCategoryAppList {
|
||||
}
|
||||
$appsByCategory[$category] += $appKey
|
||||
}
|
||||
$sync.InstallAppRenderQueue = [System.Collections.Queue]::new()
|
||||
|
||||
foreach ($category in $($appsByCategory.Keys | Sort-Object)) {
|
||||
# Create a container for category label + apps
|
||||
$categoryContainer = New-Object Windows.Controls.StackPanel
|
||||
@@ -52,10 +54,10 @@ function Initialize-InstallCategoryAppList {
|
||||
|
||||
# Add click handler to toggle category visibility
|
||||
$toggleButton.Add_MouseLeftButtonUp({
|
||||
param($sender, $e)
|
||||
param($categoryToggle)
|
||||
|
||||
# Find the parent StackPanel (categoryContainer)
|
||||
$categoryContainer = $sender.Parent
|
||||
$categoryContainer = $categoryToggle.Parent
|
||||
if ($categoryContainer -and $categoryContainer.Children.Count -ge 2) {
|
||||
# The WrapPanel is the second child
|
||||
$wrapPanel = $categoryContainer.Children[1]
|
||||
@@ -64,11 +66,11 @@ function Initialize-InstallCategoryAppList {
|
||||
if ($wrapPanel.Visibility -eq [Windows.Visibility]::Visible) {
|
||||
$wrapPanel.Visibility = [Windows.Visibility]::Collapsed
|
||||
# Change - to +
|
||||
$sender.Content = $sender.Content -replace "^- ", "+ "
|
||||
$categoryToggle.Content = $categoryToggle.Content -replace "^- ", "+ "
|
||||
} else {
|
||||
$wrapPanel.Visibility = [Windows.Visibility]::Visible
|
||||
# Change + to -
|
||||
$sender.Content = $sender.Content -replace "^\+ ", "- "
|
||||
$categoryToggle.Content = $categoryToggle.Content -replace "^\+ ", "- "
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -89,9 +91,12 @@ function Initialize-InstallCategoryAppList {
|
||||
# Add the entire category container to the target element
|
||||
$null = $TargetElement.Items.Add($categoryContainer)
|
||||
|
||||
# Add apps to the wrap panel
|
||||
$appsByCategory[$category] | Sort-Object | ForEach-Object {
|
||||
$sync.$_ = $(Initialize-InstallAppEntry -TargetElement $wrapPanel -AppKey $_)
|
||||
}
|
||||
$sync.InstallAppRenderQueue.Enqueue([pscustomobject]@{
|
||||
Category = $category
|
||||
TargetElement = $wrapPanel
|
||||
AppKeys = @($appsByCategory[$category] | Sort-Object)
|
||||
})
|
||||
}
|
||||
|
||||
Start-WinUtilInstallAppRendering
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
function Initialize-WinUtilRunspacePool {
|
||||
if ($sync.runspace -and $sync.runspace.RunspacePoolStateInfo.State -eq [System.Management.Automation.Runspaces.RunspacePoolState]::Opened) {
|
||||
return $sync.runspace
|
||||
}
|
||||
|
||||
if ($sync.runspace) {
|
||||
Close-WinUtilRunspacePool
|
||||
}
|
||||
|
||||
# Set the maximum number of threads for the RunspacePool to the number of threads on the machine.
|
||||
$maxthreads = [Math]::Max([int]$env:NUMBER_OF_PROCESSORS, 1)
|
||||
|
||||
# Create a new session state for parsing variables into our runspace.
|
||||
$hashVars = New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync', $sync, $null
|
||||
$offlineVar = New-Object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'PARAM_OFFLINE', $PARAM_OFFLINE, $null
|
||||
$initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
|
||||
|
||||
$initialSessionState.Variables.Add($hashVars)
|
||||
$initialSessionState.Variables.Add($offlineVar)
|
||||
|
||||
# Get every WinUtil/WPF function and add it to the session state.
|
||||
$functions = Get-ChildItem function:\ | Where-Object { $_.Name -imatch 'winutil|WPF' }
|
||||
foreach ($function in $functions) {
|
||||
$functionDefinition = Get-Content function:\$($function.Name)
|
||||
$functionEntry = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $function.Name, $functionDefinition
|
||||
$initialSessionState.Commands.Add($functionEntry)
|
||||
}
|
||||
|
||||
$sync.runspace = [runspacefactory]::CreateRunspacePool(
|
||||
1, # Minimum thread count
|
||||
$maxthreads, # Maximum thread count
|
||||
$initialSessionState, # Initial session state
|
||||
$Host # Machine to create runspaces on
|
||||
)
|
||||
|
||||
$sync.runspace.Open()
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Runspace pool initialized"
|
||||
return $sync.runspace
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
function Initialize-WinUtilTabContent {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TabName
|
||||
)
|
||||
|
||||
if ($null -eq $sync.InitializedTabs) {
|
||||
$sync.InitializedTabs = @{}
|
||||
}
|
||||
|
||||
if ($sync.InitializedTabs[$TabName]) {
|
||||
return
|
||||
}
|
||||
|
||||
switch ($TabName) {
|
||||
"Install" {
|
||||
Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1
|
||||
Initialize-WPFUI -targetGridName "appscategory"
|
||||
Write-WinUtilPerformanceCheckpoint -Name "App navigation UI created"
|
||||
|
||||
Initialize-WPFUI -targetGridName "appspanel"
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Install UI created"
|
||||
}
|
||||
"Tweaks" {
|
||||
Invoke-WPFUIElements -configVariable $sync.configs.tweaks -targetGridName "tweakspanel" -columncount 2
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Tweaks UI created"
|
||||
}
|
||||
"Config" {
|
||||
Invoke-WPFUIElements -configVariable $sync.configs.feature -targetGridName "featurespanel" -columncount 2
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Features UI created"
|
||||
}
|
||||
"AppX" {
|
||||
Invoke-WPFUIElements -configVariable $sync.configs.appx -targetGridName "appxpanel" -columncount 2
|
||||
Write-WinUtilPerformanceCheckpoint -Name "AppX UI created"
|
||||
}
|
||||
"Win11 Creator" {
|
||||
if ($sync.Form -and $sync.Form.Dispatcher) {
|
||||
$sync.Form.Dispatcher.BeginInvoke([System.Windows.Threading.DispatcherPriority]::Background, [action]{ Invoke-WinUtilISOCheckExistingWork }) | Out-Null
|
||||
}
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Win11 ISO tab initialized"
|
||||
}
|
||||
}
|
||||
|
||||
$sync.InitializedTabs[$TabName] = $true
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
function Initialize-WinUtilTaskbarOverlayAssets {
|
||||
param(
|
||||
[bool]$IncludeLogo = $true,
|
||||
[bool]$IncludeStatusAssets = $true
|
||||
)
|
||||
|
||||
if ($IncludeLogo -and -not $sync["logorender"]) {
|
||||
$sync["logorender"] = (Invoke-WinUtilAssets -Type "Logo" -Size 90 -Render)
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Taskbar logo asset rendered"
|
||||
}
|
||||
|
||||
if ($IncludeStatusAssets -and -not $sync["checkmarkrender"]) {
|
||||
$sync["checkmarkrender"] = (Invoke-WinUtilAssets -Type "checkmark" -Size 512 -Render)
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Taskbar checkmark asset rendered"
|
||||
}
|
||||
|
||||
if ($IncludeStatusAssets -and -not $sync["warningrender"]) {
|
||||
$sync["warningrender"] = (Invoke-WinUtilAssets -Type "warning" -Size 512 -Render)
|
||||
Write-WinUtilPerformanceCheckpoint -Name "Taskbar warning asset rendered"
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,12 @@ function Install-WinUtilProgramChoco {
|
||||
)
|
||||
|
||||
if ($Action -eq 'Install') {
|
||||
Start-Process -FilePath choco -ArgumentList "install $Programs -y" -NoNewWindow -Wait
|
||||
$arguments = "install $Programs -y"
|
||||
} else {
|
||||
Start-Process -FilePath choco -ArgumentList "uninstall $Programs -y" -NoNewWindow -Wait
|
||||
$arguments = "uninstall $Programs -y"
|
||||
}
|
||||
|
||||
Write-WinUtilLog -Component "Package" -Message "$Action choco package(s): $($Programs -join ', ')"
|
||||
$process = Start-Process -FilePath choco -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||
Write-WinUtilLog -Component "Package" -Message "$Action choco package(s) completed: $($Programs -join ', ') (exit code: $($process.ExitCode))"
|
||||
}
|
||||
|
||||
@@ -8,9 +8,25 @@ Function Install-WinUtilProgramWinget {
|
||||
[string[]]$Programs
|
||||
)
|
||||
|
||||
if ($Action -eq 'Install') {
|
||||
Start-Process -FilePath winget -ArgumentList "install $Programs --accept-package-agreements --source winget --silent" -NoNewWindow -Wait
|
||||
} else {
|
||||
Start-Process -FilePath winget -ArgumentList "uninstall $Programs --source winget --silent" -NoNewWindow -Wait
|
||||
foreach ($program in $Programs) {
|
||||
if ([string]::IsNullOrWhiteSpace($program) -or $program -eq "na") {
|
||||
continue
|
||||
}
|
||||
|
||||
$source = "winget"
|
||||
if ($program.StartsWith("msstore:", [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
$source = "msstore"
|
||||
$program = $program.Substring("msstore:".Length)
|
||||
}
|
||||
|
||||
if ($Action -eq 'Install') {
|
||||
$arguments = @("install", "--id", $program, "--accept-package-agreements", "--accept-source-agreements", "--source", $source, "--silent")
|
||||
} else {
|
||||
$arguments = @("uninstall", "--id", $program, "--source", $source, "--silent")
|
||||
}
|
||||
|
||||
Write-WinUtilLog -Component "Package" -Message "$Action winget package: $program (source: $source)"
|
||||
$process = Start-Process -FilePath winget -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||
Write-WinUtilLog -Component "Package" -Message "$Action winget package completed: $program (exit code: $($process.ExitCode))"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,17 @@ function Invoke-WinUtilAssets {
|
||||
[switch]$render
|
||||
)
|
||||
|
||||
if ($render -and $null -ne $sync) {
|
||||
if ($null -eq $sync.RenderedAssetCache) {
|
||||
$sync.RenderedAssetCache = @{}
|
||||
}
|
||||
|
||||
$cacheKey = "$(([string]$type).ToLowerInvariant())|$Size"
|
||||
if ($sync.RenderedAssetCache.ContainsKey($cacheKey)) {
|
||||
return $sync.RenderedAssetCache[$cacheKey]
|
||||
}
|
||||
}
|
||||
|
||||
# Create the Viewbox and set its size
|
||||
$LogoViewbox = New-Object Windows.Controls.Viewbox
|
||||
$LogoViewbox.Width = $Size
|
||||
@@ -191,6 +202,13 @@ C 21.36,47.14 28.67,50.71 30.01,52.63
|
||||
$bitmapImage.StreamSource = $imageStream
|
||||
$bitmapImage.CacheOption = [Windows.Media.Imaging.BitmapCacheOption]::OnLoad
|
||||
$bitmapImage.EndInit()
|
||||
if ($bitmapImage.CanFreeze) {
|
||||
$bitmapImage.Freeze()
|
||||
}
|
||||
|
||||
if ($null -ne $sync -and $sync.ContainsKey("RenderedAssetCache")) {
|
||||
$sync.RenderedAssetCache[$cacheKey] = $bitmapImage
|
||||
}
|
||||
|
||||
return $bitmapImage
|
||||
} else {
|
||||
|
||||
@@ -28,12 +28,16 @@ Function Invoke-WinUtilCurrentSystem {
|
||||
|
||||
$originalEncoding = [Console]::OutputEncoding
|
||||
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
||||
$Sync.InstalledPrograms = winget list -s winget | Select-Object -skip 3 | ConvertFrom-String -PropertyNames "Name", "Id", "Version", "Available" -Delimiter '\s{2,}'
|
||||
$Sync.InstalledPrograms = @("winget", "msstore") | ForEach-Object {
|
||||
winget list -s $psitem | Select-Object -skip 3 | ConvertFrom-String -PropertyNames "Name", "Id", "Version", "Available" -Delimiter '\s{2,}'
|
||||
}
|
||||
[Console]::OutputEncoding = $originalEncoding
|
||||
|
||||
$filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPFInstall*"}
|
||||
$sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object {
|
||||
$dependencies = @($sync.configs.applications.$($psitem.Key).winget -split ";")
|
||||
$dependencies = @($sync.configs.applications.$($psitem.Key).winget -split ";") | ForEach-Object {
|
||||
$psitem -replace "^msstore:", ""
|
||||
}
|
||||
|
||||
if ($dependencies[-1] -in $sync.InstalledPrograms.Id) {
|
||||
Write-Output $psitem.name
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
function Invoke-WinUtilFeatureInstall ($CheckBox) {
|
||||
Write-WinUtilLog -Component "Feature" -Message "Applying feature action: $CheckBox"
|
||||
|
||||
if ($sync.configs.feature.$CheckBox.feature) {
|
||||
foreach ($feature in $sync.configs.feature.$CheckBox.feature) {
|
||||
Write-Host "Installing $feature"
|
||||
Write-WinUtilLog -Component "Feature" -Message "Enabling Windows optional feature: $feature"
|
||||
Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart -ErrorAction Stop
|
||||
Write-WinUtilLog -Component "Feature" -Message "Enabled Windows optional feature: $feature"
|
||||
}
|
||||
}
|
||||
|
||||
if ($sync.configs.feature.$CheckBox.InvokeScript) {
|
||||
foreach ($script in $sync.configs.feature.$CheckBox.InvokeScript) {
|
||||
Write-Host "Running Script for $CheckBox"
|
||||
Write-WinUtilLog -Component "Feature" -Message "Running feature script for: $CheckBox"
|
||||
Invoke-Command -ScriptBlock ([scriptblock]::Create($script)) -ErrorAction Stop
|
||||
Write-WinUtilLog -Component "Feature" -Message "Completed feature script for: $CheckBox"
|
||||
}
|
||||
}
|
||||
Write-WinUtilLog -Component "Feature" -Message "Feature action completed: $CheckBox"
|
||||
}
|
||||
|
||||
@@ -213,6 +213,59 @@ function Invoke-WinUtilISOModify {
|
||||
})
|
||||
}
|
||||
|
||||
function Get-WinUtilEditionIdFromName {
|
||||
param([string]$EditionName)
|
||||
|
||||
$normalizedName = ($EditionName -replace '^Windows\s+11\s+', '').Trim()
|
||||
switch -Regex ($normalizedName) {
|
||||
'^Home Single Language$' { return 'CoreSingleLanguage' }
|
||||
'^Home N$' { return 'CoreN' }
|
||||
'^Home$' { return 'Core' }
|
||||
'^Pro for Workstations N$' { return 'ProfessionalWorkstationN' }
|
||||
'^Pro for Workstations$' { return 'ProfessionalWorkstation' }
|
||||
'^Pro Education N$' { return 'ProfessionalEducationN' }
|
||||
'^Pro Education$' { return 'ProfessionalEducation' }
|
||||
'^Pro N$' { return 'ProfessionalN' }
|
||||
'^Pro$' { return 'Professional' }
|
||||
'^Education N$' { return 'EducationN' }
|
||||
'^Education$' { return 'Education' }
|
||||
'^Enterprise LTSC N$' { return 'EnterpriseSN' }
|
||||
'^Enterprise LTSC$' { return 'EnterpriseS' }
|
||||
'^Enterprise N$' { return 'EnterpriseN' }
|
||||
'^Enterprise$' { return 'Enterprise' }
|
||||
default { return '' }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-WinUtilMountedImageEditionId {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$MountDir,
|
||||
[string]$EditionName,
|
||||
[scriptblock]$Logger
|
||||
)
|
||||
|
||||
try {
|
||||
$dismOutput = & dism /English "/Image:$MountDir" /Get-CurrentEdition 2>&1
|
||||
foreach ($line in $dismOutput) {
|
||||
if ($line -match '^\s*Current Edition\s*:\s*(.+?)\s*$') {
|
||||
$editionId = $Matches[1].Trim()
|
||||
if ($editionId) {
|
||||
if ($Logger) { $null = $Logger.Invoke("Detected mounted image EditionID: $editionId") }
|
||||
return $editionId
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if ($Logger) { $null = $Logger.Invoke("Warning: could not detect mounted image EditionID with DISM: $_") }
|
||||
}
|
||||
|
||||
$fallbackEditionId = Get-WinUtilEditionIdFromName -EditionName $EditionName
|
||||
if ($fallbackEditionId -and $Logger) {
|
||||
$null = $Logger.Invoke("Using fallback EditionID '$fallbackEditionId' from selected edition name.")
|
||||
}
|
||||
return $fallbackEditionId
|
||||
}
|
||||
|
||||
function Get-DismImageInfoMap {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$ImagePath,
|
||||
@@ -322,9 +375,10 @@ function Invoke-WinUtilISOModify {
|
||||
Log "Mounting install.wim (Index ${selectedWimIndex}: $selectedEditionName) at $mountDir..."
|
||||
Mount-WindowsImage -ImagePath $localWim -Index $selectedWimIndex -Path $mountDir
|
||||
SetProgress "Modifying install.wim..." 45
|
||||
$selectedEditionId = Get-WinUtilMountedImageEditionId -MountDir $mountDir -EditionName $selectedEditionName -Logger ${function:Log}
|
||||
|
||||
Log "Applying WinUtil modifications to install.wim..."
|
||||
Invoke-WinUtilISOScript -ScratchDir $mountDir -ISOContentsDir $isoContents -AutoUnattendXml $autounattendContent -InjectCurrentSystemDrivers $injectDrivers -Log { param($m) Log $m }
|
||||
Invoke-WinUtilISOScript -ScratchDir $mountDir -ISOContentsDir $isoContents -AutoUnattendXml $autounattendContent -InjectCurrentSystemDrivers $injectDrivers -InstallEditionId $selectedEditionId -InstallImageIndex 1 -Log { param($m) Log $m }
|
||||
|
||||
SetProgress "Cleaning up component store (WinSxS)..." 56
|
||||
Log "Running DISM component store cleanup (/ResetBase)..."
|
||||
|
||||
@@ -34,6 +34,16 @@ function Invoke-WinUtilISOScript {
|
||||
them into install.wim and boot.wim index 2 (Windows Setup PE).
|
||||
Defaults to $false.
|
||||
|
||||
.PARAMETER InstallEditionId
|
||||
Optional. Windows edition ID for the selected image, for example Professional
|
||||
or Core. Used to write sources\ei.cfg so setup does not fall back to an
|
||||
embedded firmware product key for a different edition.
|
||||
|
||||
.PARAMETER InstallImageIndex
|
||||
Optional. Image index that setup should install from the final install.wim.
|
||||
Win11 Creator exports the selected edition to a single-image WIM, so this
|
||||
defaults to 1.
|
||||
|
||||
.PARAMETER Log
|
||||
Optional ScriptBlock for progress/status logging. Receives a single [string] argument.
|
||||
|
||||
@@ -56,6 +66,8 @@ function Invoke-WinUtilISOScript {
|
||||
[string]$ISOContentsDir = "",
|
||||
[string]$AutoUnattendXml = "",
|
||||
[bool]$InjectCurrentSystemDrivers = $false,
|
||||
[string]$InstallEditionId = "",
|
||||
[int]$InstallImageIndex = 1,
|
||||
[scriptblock]$Log = { param($m) Write-Output $m }
|
||||
)
|
||||
|
||||
@@ -108,6 +120,146 @@ function Invoke-WinUtilISOScript {
|
||||
}
|
||||
}
|
||||
|
||||
function Get-WinUtilISOScriptChildElement {
|
||||
param (
|
||||
[Parameter(Mandatory)][System.Xml.XmlElement]$Parent,
|
||||
[Parameter(Mandatory)][string]$Name,
|
||||
[Parameter(Mandatory)][string]$NamespaceUri
|
||||
)
|
||||
|
||||
foreach ($childNode in $Parent.ChildNodes) {
|
||||
if ($childNode.NodeType -eq [System.Xml.XmlNodeType]::Element -and
|
||||
$childNode.LocalName -eq $Name -and
|
||||
$childNode.NamespaceURI -eq $NamespaceUri) {
|
||||
return [System.Xml.XmlElement]$childNode
|
||||
}
|
||||
}
|
||||
|
||||
$childElement = $Parent.OwnerDocument.CreateElement($Name, $NamespaceUri)
|
||||
[void]$Parent.AppendChild($childElement)
|
||||
return $childElement
|
||||
}
|
||||
|
||||
function ConvertTo-WinUtilISOAnswerFile {
|
||||
param (
|
||||
[Parameter(Mandatory)][string]$XmlContent,
|
||||
[int]$ImageIndex = 1
|
||||
)
|
||||
|
||||
if ($ImageIndex -lt 1) { $ImageIndex = 1 }
|
||||
|
||||
$unattendNs = "urn:schemas-microsoft-com:unattend"
|
||||
$wcmNs = "http://schemas.microsoft.com/WMIConfig/2002/State"
|
||||
|
||||
$xmlDoc = [xml]::new()
|
||||
$xmlDoc.PreserveWhitespace = $true
|
||||
$xmlDoc.LoadXml($XmlContent)
|
||||
|
||||
if ($xmlDoc.DocumentElement.NamespaceURI -ne $unattendNs) {
|
||||
throw "Unexpected autounattend.xml namespace: $($xmlDoc.DocumentElement.NamespaceURI)"
|
||||
}
|
||||
|
||||
if (-not $xmlDoc.DocumentElement.HasAttribute("xmlns:wcm")) {
|
||||
$xmlDoc.DocumentElement.SetAttribute("wcm", "http://www.w3.org/2000/xmlns/", $wcmNs)
|
||||
}
|
||||
|
||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||
$nsMgr.AddNamespace("u", $unattendNs)
|
||||
|
||||
$windowsPESettings = $xmlDoc.SelectSingleNode('/u:unattend/u:settings[@pass="windowsPE"]', $nsMgr)
|
||||
if (-not $windowsPESettings) {
|
||||
$windowsPESettings = $xmlDoc.CreateElement("settings", $unattendNs)
|
||||
$windowsPESettings.SetAttribute("pass", "windowsPE")
|
||||
[void]$xmlDoc.DocumentElement.PrependChild($windowsPESettings)
|
||||
}
|
||||
|
||||
$setupComponent = $windowsPESettings.SelectSingleNode('u:component[@name="Microsoft-Windows-Setup"]', $nsMgr)
|
||||
if (-not $setupComponent) {
|
||||
$setupComponent = $xmlDoc.CreateElement("component", $unattendNs)
|
||||
$setupComponent.SetAttribute("name", "Microsoft-Windows-Setup")
|
||||
$setupComponent.SetAttribute("processorArchitecture", "amd64")
|
||||
$setupComponent.SetAttribute("publicKeyToken", "31bf3856ad364e35")
|
||||
$setupComponent.SetAttribute("language", "neutral")
|
||||
$setupComponent.SetAttribute("versionScope", "nonSxS")
|
||||
[void]$windowsPESettings.AppendChild($setupComponent)
|
||||
}
|
||||
|
||||
$productKeyNodes = @($setupComponent.SelectNodes("u:UserData/u:ProductKey", $nsMgr))
|
||||
foreach ($productKeyNode in $productKeyNodes) {
|
||||
$keyNode = $productKeyNode.SelectSingleNode("u:Key", $nsMgr)
|
||||
$keyValue = if ($keyNode) { $keyNode.InnerText.Trim() } else { "" }
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($keyValue) -or $keyValue -eq "00000-00000-00000-00000-00000") {
|
||||
[void]$productKeyNode.ParentNode.RemoveChild($productKeyNode)
|
||||
}
|
||||
}
|
||||
|
||||
$imageInstall = Get-WinUtilISOScriptChildElement -Parent $setupComponent -Name "ImageInstall" -NamespaceUri $unattendNs
|
||||
$osImage = Get-WinUtilISOScriptChildElement -Parent $imageInstall -Name "OSImage" -NamespaceUri $unattendNs
|
||||
$installFrom = Get-WinUtilISOScriptChildElement -Parent $osImage -Name "InstallFrom" -NamespaceUri $unattendNs
|
||||
|
||||
$existingMetadataNodes = @($installFrom.SelectNodes("u:MetaData", $nsMgr))
|
||||
foreach ($metadataNode in $existingMetadataNodes) {
|
||||
[void]$installFrom.RemoveChild($metadataNode)
|
||||
}
|
||||
|
||||
$metadata = $xmlDoc.CreateElement("MetaData", $unattendNs)
|
||||
$actionAttribute = $xmlDoc.CreateAttribute("wcm", "action", $wcmNs)
|
||||
$actionAttribute.Value = "add"
|
||||
[void]$metadata.Attributes.Append($actionAttribute)
|
||||
|
||||
$keyElement = $xmlDoc.CreateElement("Key", $unattendNs)
|
||||
$keyElement.InnerText = "/IMAGE/INDEX"
|
||||
[void]$metadata.AppendChild($keyElement)
|
||||
|
||||
$valueElement = $xmlDoc.CreateElement("Value", $unattendNs)
|
||||
$valueElement.InnerText = [string]$ImageIndex
|
||||
[void]$metadata.AppendChild($valueElement)
|
||||
|
||||
[void]$installFrom.AppendChild($metadata)
|
||||
|
||||
return $xmlDoc.OuterXml
|
||||
}
|
||||
|
||||
function Write-WinUtilISOEditionConfig {
|
||||
param (
|
||||
[Parameter(Mandatory)][string]$ContentRoot,
|
||||
[string]$EditionId,
|
||||
[scriptblock]$Logger
|
||||
)
|
||||
|
||||
if (-not (Test-Path $ContentRoot)) {
|
||||
return
|
||||
}
|
||||
|
||||
$sourcesDir = Join-Path $ContentRoot "sources"
|
||||
New-Item -Path $sourcesDir -ItemType Directory -Force | Out-Null
|
||||
|
||||
$pidPath = Join-Path $sourcesDir "PID.txt"
|
||||
if (Test-Path $pidPath) {
|
||||
Remove-Item -Path $pidPath -Force
|
||||
& $Logger "Removed sources\PID.txt so setup will not force a stale or mismatched product key."
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($EditionId)) {
|
||||
& $Logger "Warning: selected edition ID is unknown - skipping sources\ei.cfg fallback."
|
||||
return
|
||||
}
|
||||
|
||||
$eiCfgPath = Join-Path $sourcesDir "ei.cfg"
|
||||
$eiCfg = @"
|
||||
[EditionID]
|
||||
$EditionId
|
||||
[Channel]
|
||||
Retail
|
||||
[VL]
|
||||
0
|
||||
"@.Trim()
|
||||
|
||||
Set-Content -Path $eiCfgPath -Value $eiCfg -Encoding ASCII -Force
|
||||
& $Logger "Written sources\ei.cfg for EditionID '$EditionId'."
|
||||
}
|
||||
|
||||
# -- 1. Remove provisioned AppX packages ----------------------------------
|
||||
& $Log "Removing provisioned AppX packages..."
|
||||
|
||||
@@ -218,9 +370,17 @@ function Invoke-WinUtilISOScript {
|
||||
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE' 'BypassNRO' 'REG_DWORD' '1'
|
||||
|
||||
if ($AutoUnattendXml) {
|
||||
$preparedAutoUnattendXml = $AutoUnattendXml
|
||||
try {
|
||||
$preparedAutoUnattendXml = ConvertTo-WinUtilISOAnswerFile -XmlContent $AutoUnattendXml -ImageIndex $InstallImageIndex
|
||||
& $Log "Prepared autounattend.xml to install image index $InstallImageIndex without forcing a product key."
|
||||
} catch {
|
||||
& $Log "Warning: could not prepare autounattend.xml image selection: $_"
|
||||
}
|
||||
|
||||
try {
|
||||
$xmlDoc = [xml]::new()
|
||||
$xmlDoc.LoadXml($AutoUnattendXml)
|
||||
$xmlDoc.LoadXml($preparedAutoUnattendXml)
|
||||
|
||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||
$nsMgr.AddNamespace("sg", "https://schneegans.de/windows/unattend-generator/")
|
||||
@@ -251,13 +411,17 @@ function Invoke-WinUtilISOScript {
|
||||
|
||||
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
|
||||
$isoDest = Join-Path $ISOContentsDir "autounattend.xml"
|
||||
Set-Content -Path $isoDest -Value $AutoUnattendXml -Encoding UTF8 -Force
|
||||
Set-Content -Path $isoDest -Value $preparedAutoUnattendXml -Encoding UTF8 -Force
|
||||
& $Log "Written autounattend.xml to ISO root ($isoDest)."
|
||||
}
|
||||
} else {
|
||||
& $Log "Warning: autounattend.xml content is empty - skipping OOBE bypass file."
|
||||
}
|
||||
|
||||
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
|
||||
Write-WinUtilISOEditionConfig -ContentRoot $ISOContentsDir -EditionId $InstallEditionId -Logger $Log
|
||||
}
|
||||
|
||||
& $Log "Disabling reserved storage..."
|
||||
Set-ISOScriptReg 'HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager' 'ShippedWithReserves' 'REG_DWORD' '0'
|
||||
|
||||
|
||||
@@ -22,23 +22,30 @@ function Invoke-WinUtilScript {
|
||||
|
||||
try {
|
||||
Write-Host "Running Script for $Name"
|
||||
Write-WinUtilLog -Component "Script" -Message "Running script for $Name"
|
||||
Invoke-Command $scriptblock -ErrorAction Stop
|
||||
Write-WinUtilLog -Component "Script" -Message "Completed script for $Name"
|
||||
} catch [System.Management.Automation.CommandNotFoundException] {
|
||||
Write-Warning "The specified command was not found."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Script" -Message "Command not found while running script for $Name`: $($PSItem.Exception.Message)"
|
||||
} catch [System.Management.Automation.RuntimeException] {
|
||||
Write-Warning "A runtime exception occurred."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Script" -Message "Runtime exception while running script for $Name`: $($PSItem.Exception.Message)"
|
||||
} catch [System.Security.SecurityException] {
|
||||
Write-Warning "A security exception occurred."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Script" -Message "Security exception while running script for $Name`: $($PSItem.Exception.Message)"
|
||||
} catch [System.UnauthorizedAccessException] {
|
||||
Write-Warning "Access denied. You do not have permission to perform this operation."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Script" -Message "Access denied while running script for $Name`: $($PSItem.Exception.Message)"
|
||||
} catch {
|
||||
# Generic catch block to handle any other type of exception
|
||||
Write-Warning "Unable to run script for $Name due to unhandled exception."
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Script" -Message "Unhandled exception while running script for $Name`: $($psitem.Exception.Message)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ function Invoke-WinUtilTweaks {
|
||||
$KeepServiceStartup = $true
|
||||
)
|
||||
|
||||
$action = if ($undo) { "Undo" } else { "Apply" }
|
||||
Write-WinUtilLog -Component "Tweaks" -Message "$action tweak: $CheckBox"
|
||||
|
||||
if ($undo) {
|
||||
$Values = @{
|
||||
Registry = "OriginalValue"
|
||||
@@ -77,4 +80,5 @@ function Invoke-WinUtilTweaks {
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-WinUtilLog -Component "Tweaks" -Message "$action tweak completed: $CheckBox"
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ function Remove-WinUtilAPPX {
|
||||
)
|
||||
|
||||
Write-Host "Removing $Name"
|
||||
Write-WinUtilLog -Component "AppX" -Message "Removing AppX package pattern: $Name"
|
||||
Get-AppxPackage $Name -AllUsers | Remove-AppxPackage -AllUsers
|
||||
Get-AppxProvisionedPackage -Online | Where-Object DisplayName -like $Name | Remove-AppxProvisionedPackage -Online
|
||||
Write-WinUtilLog -Component "AppX" -Message "AppX removal completed for package pattern: $Name"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ function Reset-WPFCheckBoxes {
|
||||
[string]$checkboxfilterpattern = "**"
|
||||
)
|
||||
|
||||
$CheckBoxesToCheck = $sync.selectedApps + $sync.selectedTweaks + $sync.selectedFeatures
|
||||
$CheckBoxesToCheck = $sync.selectedApps + $sync.selectedTweaks + $sync.selectedFeatures + $sync.selectedAppx
|
||||
$CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
|
||||
|
||||
foreach ($CheckBox in $CheckBoxes) {
|
||||
|
||||
@@ -12,22 +12,31 @@ function Set-WinUtilDNS {
|
||||
|
||||
#>
|
||||
param($DNSProvider)
|
||||
if($DNSProvider -eq "Default") {return}
|
||||
if($DNSProvider -eq "Default") {
|
||||
Write-WinUtilLog -Component "DNS" -Message "DNS provider is Default; no DNS changes applied."
|
||||
return
|
||||
}
|
||||
try {
|
||||
$Adapters = Get-NetAdapter | Where-Object {$_.Status -eq "Up"}
|
||||
Write-Host "Ensuring DNS is set to $DNSProvider on the following interfaces:"
|
||||
Write-Host $($Adapters | Out-String)
|
||||
Write-WinUtilLog -Component "DNS" -Message "Setting DNS provider to $DNSProvider for $(@($Adapters).Count) active adapter(s)."
|
||||
|
||||
Foreach ($Adapter in $Adapters) {
|
||||
if($DNSProvider -eq "DHCP") {
|
||||
Write-WinUtilLog -Component "DNS" -Message "Resetting DNS to DHCP on adapter $($Adapter.Name) (ifIndex: $($Adapter.ifIndex))."
|
||||
Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ResetServerAddresses
|
||||
} else {
|
||||
Write-WinUtilLog -Component "DNS" -Message "Setting IPv4 DNS on adapter $($Adapter.Name) (ifIndex: $($Adapter.ifIndex)) to $($sync.configs.dns.$DNSProvider.Primary), $($sync.configs.dns.$DNSProvider.Secondary)."
|
||||
Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ServerAddresses ("$($sync.configs.dns.$DNSProvider.Primary)", "$($sync.configs.dns.$DNSProvider.Secondary)")
|
||||
Write-WinUtilLog -Component "DNS" -Message "Setting IPv6 DNS on adapter $($Adapter.Name) (ifIndex: $($Adapter.ifIndex)) to $($sync.configs.dns.$DNSProvider.Primary6), $($sync.configs.dns.$DNSProvider.Secondary6)."
|
||||
Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ServerAddresses ("$($sync.configs.dns.$DNSProvider.Primary6)", "$($sync.configs.dns.$DNSProvider.Secondary6)")
|
||||
}
|
||||
}
|
||||
Write-WinUtilLog -Component "DNS" -Message "DNS provider change completed: $DNSProvider"
|
||||
} catch {
|
||||
Write-Warning "Unable to set DNS Provider due to an unhandled exception."
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
Write-WinUtilLog -Level "ERROR" -Component "DNS" -Message "Unable to set DNS provider $DNSProvider`: $($psitem.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,25 +32,32 @@ function Set-WinUtilRegistry {
|
||||
|
||||
If (!(Test-Path $Path)) {
|
||||
Write-Host "$Path was not found. Creating..."
|
||||
Write-WinUtilLog -Component "Registry" -Message "Creating registry path: $Path"
|
||||
New-Item -Path $Path -Force -ErrorAction Stop | Out-Null
|
||||
}
|
||||
|
||||
if ($Value -ne "<RemoveEntry>") {
|
||||
Write-Host "Set $Path\$Name to $Value"
|
||||
Write-WinUtilLog -Component "Registry" -Message "Setting $Path\$Name ($Type) to $Value"
|
||||
Set-ItemProperty -Path $Path -Name $Name -Type $Type -Value $Value -Force -ErrorAction Stop | Out-Null
|
||||
}
|
||||
else{
|
||||
Write-Host "Remove $Path\$Name"
|
||||
Write-WinUtilLog -Component "Registry" -Message "Removing $Path\$Name"
|
||||
Remove-ItemProperty -Path $Path -Name $Name -Force -ErrorAction Stop | Out-Null
|
||||
}
|
||||
} catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception."
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Registry" -Message "Security exception while changing $Path\$Name to $Value`: $($psitem.Exception.Message)"
|
||||
} catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Registry" -Message "Registry item not found while changing $Path\$Name`: $($psitem.Exception.Message)"
|
||||
} catch [System.UnauthorizedAccessException] {
|
||||
Write-Warning $psitem.Exception.Message
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Registry" -Message "Unauthorized while changing $Path\$Name`: $($psitem.Exception.Message)"
|
||||
} catch {
|
||||
Write-Warning "Unable to set $Name due to unhandled exception."
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Registry" -Message "Unhandled exception while changing $Path\$Name`: $($psitem.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,21 +20,33 @@ Function Set-WinUtilService {
|
||||
)
|
||||
try {
|
||||
Write-Host "Setting Service $Name to $StartupType"
|
||||
Write-WinUtilLog -Component "Service" -Message "Setting service $Name startup type to $StartupType"
|
||||
|
||||
# Check if the service exists
|
||||
$service = Get-Service -Name $Name -ErrorAction Stop
|
||||
|
||||
if (($service.PSObject.Properties.Name -contains "StartType") -and ([string]$service.StartType -eq [string]$StartupType) ) {
|
||||
Write-Host "Service $Name is already set to $StartupType"
|
||||
Write-WinUtilLog -Component "Service" -Message "Service $Name startup type is already $StartupType; no change needed."
|
||||
return
|
||||
}
|
||||
|
||||
# Service exists, proceed with changing properties -- while handling auto delayed start for PWSH 5
|
||||
if (($PSVersionTable.PSVersion.Major -lt 7) -and ($StartupType -eq "AutomaticDelayedStart")) {
|
||||
sc.exe config $Name start=delayed-auto
|
||||
} else {
|
||||
$service | Set-Service -StartupType $StartupType -ErrorAction Stop
|
||||
}
|
||||
} catch [System.ServiceProcess.ServiceNotFoundException] {
|
||||
Write-Warning "Service $Name was not found."
|
||||
Write-WinUtilLog -Component "Service" -Message "Service $Name startup type set to $StartupType"
|
||||
} catch {
|
||||
Write-Warning "Unable to set $Name due to unhandled exception."
|
||||
Write-Warning $_.Exception.Message
|
||||
if ($_.FullyQualifiedErrorId -like "NoServiceFoundForGivenName,*") {
|
||||
Write-Warning "Service $Name was not found."
|
||||
Write-WinUtilLog -Level "WARN" -Component "Service" -Message "Service $Name was not found."
|
||||
} else {
|
||||
Write-Warning "Unable to set $Name due to unhandled exception."
|
||||
Write-Warning $_.Exception.Message
|
||||
Write-WinUtilLog -Level "ERROR" -Component "Service" -Message "Unable to set service $Name to $StartupType`: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,12 +61,21 @@ function Set-WinUtilTaskbaritem {
|
||||
if ($overlay) {
|
||||
switch ($overlay) {
|
||||
'logo' {
|
||||
if (-not $sync["logorender"]) {
|
||||
Initialize-WinUtilTaskbarOverlayAssets -IncludeLogo $true -IncludeStatusAssets $false
|
||||
}
|
||||
$sync["Form"].taskbarItemInfo.Overlay = $sync["logorender"]
|
||||
}
|
||||
'checkmark' {
|
||||
if (-not $sync["checkmarkrender"]) {
|
||||
Initialize-WinUtilTaskbarOverlayAssets -IncludeLogo $false -IncludeStatusAssets $true
|
||||
}
|
||||
$sync["Form"].taskbarItemInfo.Overlay = $sync["checkmarkrender"]
|
||||
}
|
||||
'warning' {
|
||||
if (-not $sync["warningrender"]) {
|
||||
Initialize-WinUtilTaskbarOverlayAssets -IncludeLogo $false -IncludeStatusAssets $true
|
||||
}
|
||||
$sync["Form"].taskbarItemInfo.Overlay = $sync["warningrender"]
|
||||
}
|
||||
'None' {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user