One stop shop for common Windows 11 tasks
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
reinitialized 75b3897d31
Some checks failed
Pester / windows-powershell-51 (push) Waiting to run
Pester / portable-pwsh (push) Failing after 10m57s
Document deep-dive root causes, remediation commits, and validation
2026-09-04 20:22:33 -05:00
.forgejo/workflows Stop "stop" starting a destructive run, and run the gate the README promises 2026-09-03 14:45:21 -05:00
config Delete two config knobs that were read by nothing 2026-09-03 15:00:32 -05:00
modules Forward native update reboot evidence into resume handoff 2026-09-04 20:15:49 -05:00
tests Ratchet source assertions after reset and software behavior tests 2026-09-04 20:16:19 -05:00
tools Return software run outcomes and verify applied app changes 2026-09-04 20:16:12 -05:00
wiki Document deep-dive root causes, remediation commits, and validation 2026-09-04 20:22:33 -05:00
.gitignore Enhance Factory Reset and Repair Workstation Scripts 2026-08-13 12:30:54 -05:00
AGENTS.md Document the force-gate contract and correct documentation drift 2026-08-28 19:24:50 -05:00
flake.lock extensive improvements to SolveOnedriveDuplicates 2026-02-11 21:08:34 -06:00
flake.nix Document the force-gate contract and correct documentation drift 2026-08-28 19:24:50 -05:00
README.md Stop "stop" starting a destructive run, and run the gate the README promises 2026-09-03 14:45:21 -05:00
start.ps1 Report differing repository tips without assuming commit order 2026-09-04 20:07:59 -05:00

TechWizard

TechWizard is the Reinitialized.net TechTools launcher for Windows 11 workstation provisioning, repair, cleanup, profile migration, RMM agent maintenance, and OneDrive duplicate resolution.

The single entry point is start.ps1. It can run from a local checkout or be launched directly from Forgejo with PowerShell.

TechWizard v2 keeps start.ps1 as a thin bootstrap. Tool metadata now lives in modules/TechTools.Manifest.psm1, and launcher behavior lives in modules/TechTools.Launcher.psm1. Domain modules and tool scripts continue to own the workstation operations.

Contributors can run the portable Pester suite with nix develop --no-write-lock-file -c pwsh -File ./tests/run-tests.ps1. Forgejo also runs the full suite under the production Windows PowerShell 5.1 runtime; both gates must remain green. See AGENTS.md for architecture and safety contracts.

Quick Start From Forgejo

Open Windows Terminal or PowerShell as Administrator, then run:

Set-ExecutionPolicy Bypass -Scope Process -Force; $RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'; & ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) -RepoBaseUrl $RepoBaseUrl

Set-ExecutionPolicy Bypass -Scope Process -Force relaxes the policy for the current PowerShell process only, so a strict machine or user Execution Policy does not block the remote launch. It is not persisted and does not change the configured Execution Policy.

This downloads start.ps1 from Forgejo, opens the interactive tool menu, and loads the selected tool, modules, and config files from the same branch.

On a fresh interactive menu launch TechWizard offers to pivot the session into a temporary superadministrator (it creates the account, signs you out, and the menu relaunches under that account with maximum privileges). It always asks first — Proceed? [y/N], where plain Enter declines — and answering n simply continues in the current session. The pivot is never offered for -Tool or -AcceptAll launches.

The canonical raw launch examples use https://git.ds.reinitialized.net/reinitialized.net/TechWizard. If a reinitialized.studio/TechWizard URL is published for operators, treat it as an alias only when it resolves to the same repository and branch; otherwise keep -RepoBaseUrl aligned to the canonical namespace to avoid duplicate cache roots.

To launch a specific tool without the menu:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Repair-Workstation

To run unattended and suppress confirmation prompts, use -AcceptAll with a specific tool:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Prepare-System `
    -AcceptAll

To run only a specific phase, pass -ToolArgs:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Repair-Workstation `
    -ToolArgs @{ Phase = 'Cleanup'; Force = $true }

To validate inputs and view the manifest-backed run plan without executing the tool, add -Preview:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Repair-Workstation `
    -ToolArgs @{ Phase = 'Cleanup' } `
    -Preview

The interactive menu is a single screen: a TechWizard masthead with host context (computer, operator, run source, client overlay, elevated-session badges), the tools grouped by category with continuous numbering and human display titles, and the recommended new-workstation sequence. You can pick a tool by number or just type its name or an alias. Interactive launch defaults to -UiMode Auto, which uses the guided wizard variant where practical: -UiMode Wizard adds each tool's when-to-use guidance and its time/data-loss/reboot tag under every entry, while -UiMode Classic keeps one compact line per tool.

Every menu-driven launch ends in a pre-flight card (what will run, estimated time, reboot/data-loss expectations, the ordered phase plan with destructive markers) followed by a gate. When the run includes no destructive phase, Enter starts it; when it does, the destructive phases are listed and you must type Y — a bare Enter is refused. E changes your answers, Q returns to the menu. Because an unexpanded All or Auto selection counts every destructive phase as in play, the Y form is what you see for a default Repair-Workstation, Prepare-System or Factory-Reset run. After a run finishes the launcher offers to return to the menu so you can chain tools without relaunching. The gate and the return-to-menu prompt only appear on a live interactive console — -Tool, -AcceptAll, force mode, resume runs, and headless sessions never see them, so automation behaves exactly as before.

Simple enable/disable utilities (for example Web Sign-In and the Windows Hello PIN policy) appear as a single menu entry; selecting one opens a small second-level menu to choose Enable or Disable before the run starts. Launching those tools directly with -Tool still takes the action from -ToolArgs. Each tool has its own vocabulary: Web Sign-In takes -ToolArgs @{ Mode = 'Enable' } or 'Disable', while the Windows Hello PIN policy takes -ToolArgs @{ Mode = 'Allow' } or 'Prevent'.

Available Tools

The menu is edition-aware: it shows only the tools supported by the current Windows edition (client vs. server / domain controller). On a workstation the client tools below appear; on a domain controller or an RSAT-equipped admin workstation the Active Directory tools appear.

Tool Purpose
Repair-Workstation Deep-analyzes the OS and auto-runs only the repair phases a problem was found for — Windows image repair, OEM/Windows updates plus third-party software currency (winget), device-driver detection and repair, profile repair, cleanup, and RMM agent validation and install/repair. A deep Event Viewer analysis (with best-practice maintenance checks) runs as part of Auto only; it is not a hand-selectable phase.
Factory-Reset Resets a workstation to the MSP baseline, preserving RMM while removing non-whitelisted apps and stale profiles. Defaults to Auto: a read-only analysis (image health, updates, bloatware/UI baseline, the app removal plan, break-glass admin state, the account/profile cleanup plan, disk space, RMM health) picks only the phases whose baseline goal is not already satisfied; All forces the full reset.
Prepare-System Analyzes the OS (incl. Event Logs) and auto-runs only the provisioning phases not already satisfied. Its SecurityAgents phase runs first: approved endpoint-security products are retained only after health validation; approved but misconfigured and non-approved supported products are removal targets; unsupported, inconclusive, or failed teardown blocks provisioning. Successful retention or teardown hands off to Debloat, then Apps; any required endpoint-security re-installation remains an external RMM/MDM responsibility.
Remove-SecurityAgents Classifies detected endpoint security as ApprovedHealthy, ApprovedMisconfigured, Unauthorized, Unsupported, or Inconclusive, with a validation-only option. Approved healthy products remain installed; approved but misconfigured products are removed for external re-installation; non-approved supported products are removed. ESET and consumer McAfee use the native teardown engine, while SentinelOne remains detection-only except for its disabled-by-default, externally configured verified vendor-cleaner adapter. Removal requires elevation, dangerous default-No confirmation that -Force cannot bypass, and ShouldProcess.
SolveOnedriveDuplicates Scans and resolves OneDrive duplicate, conflict, and near-duplicate files with backups.
Restore-OneDriveBackup Reverts OneDrive duplicate-resolution operations from a timestamped backup folder.
Migrate-UserProfile Uses USMT hard-link migration to move one local Windows profile into a fresh local account. Must run as NT AUTHORITY\SYSTEM for real migrations (e.g. psexec.exe -i -s powershell.exe -ExecutionPolicy Bypass -File .\tools\Process\Migrate-UserProfile.ps1); an elevated-but-non-SYSTEM launch stops at the SYSTEM gate with that guidance.
Enable-WebSignIn Enables or disables the Web Sign-In credential provider for Entra-joined Windows 11 workstations.
Set-WindowsHelloPinPolicy Allows or prevents Windows from requesting/requiring a Windows Hello PIN (toggles Windows Hello for Business provisioning at the device scope).
Clear-WindowsHelloPin Forcefully clears a selected user profile's Windows Hello PIN (NGC container) — e.g. a leftover PIN enrolled during TAP-based white-glove setup — with backup and best-effort per-SID targeting.
Set-Microsoft365Apps Fully customizes the Microsoft 365 installation per app: add or remove individual Office applications (Word, Excel, Access, Publisher, Teams, OneNote, classic Outlook, ...) via the Office Deployment Tool, or fresh-install a custom app set on a machine without Office. Unattended runs change nothing unless apps are named explicitly; removals and classic-Outlook re-adds require dangerous confirmation. Running Office apps must be closed for the change to apply (Click-to-Run otherwise cancels the silent pass with exit 17006), so detected running apps are force-closed after an explicit dangerous confirmation.
Test-InternetHealth Traces the path to a target and live-monitors every hop's latency, loss, and jitter, PingPlotter-style, on a flicker-free console dashboard with a per-hop latency-history graph. A running point-of-failure diagnosis separates real end-to-end loss from routers that merely rate-limit their ICMP replies (the classic traceroute false positive), names the segment where a real failure enters the path (local network / ISP handoff / internet / destination), and distinguishes problems happening right now from an earlier episode. Q / Esc / Ctrl+C stop it cleanly — final statistics, the diagnosis, and the optional per-hop CSV export survive the stop even in continuous mode. Read-only.
Repair-MappedDrives Makes a user's mapped network drives survive VPN/network reconnects — the permanent fix for "an error occurred while reconnecting X: ... the local device name is already in use" and for "system error 1219" credential conflicts. Discovers the target user's mappings from their registry hive (works from an elevated run-as-different-admin session), converts them to non-persistent, and drives them from two scheduled tasks running under the user's own interactive token (no stored password, no elevation, and fully hidden — the batch scripts run through a wscript launcher so no console window ever flashes on the user's desktop when the network churns): remap at logon and on network/VPN connect (NetworkProfile event 10000, VPN-client-agnostic) with quoted UNC paths and a settle delay, release all drive letters on disconnect (event 10001). Optional per-reconnect saved-credential cleanup for the mapped file servers (the 1219 fix, confirmed separately), a GPO Drive Maps conflict warning, Status and Uninstall modes, and an uninstall rollback that restores classic persistent mappings at the user's next sign-in.
Clean-ADStaleObjects Safely retires stale on-prem AD computer/user objects: scan → report → disable → quarantine, with opt-in permanent purge and a reversible transaction log. (domain controller / RSAT only)
Clear-ADDisabledAccountGroups Strips group memberships from disabled on-prem AD user accounts (their primary group is never touched), with a reversible transaction log so removed memberships can be restored. (domain controller / RSAT only)
Export-ADGroupMembers Exports the members of an on-prem AD group (direct members) to CSV for documentation and access reviews. Read-only. (domain controller / RSAT only)
Install-Software Installs a chosen subset of the supported software catalog (required-tools.psd1) on demand — winget first with the manifest's direct-download fallback — without running the full provisioning flow.
Find-NetworkAssets Discovers and classifies the devices on a network with nmap — printers, servers, domain controllers, hypervisors, NAS, switches/firewalls/APs, VoIP phones, cameras, and workstations — for on-site setup when the documentation is missing. Auto-detects the local subnet (or takes an explicit CIDR/range/host), fingerprints open services and guesses the OS, and exports a grouped inventory as CSV, JSON, and a shareable HTML report. Installs nmap (with the Npcap driver) on demand via winget. Read-only against scanned devices; it is an active scan, so only run it on networks you are authorized to scan.

Endpoint Security Removal

TechTools.SecurityAgent owns endpoint-security detection, validation, and removal. TechTools.Debloat never removes endpoint security itself; when its optional security hook is enabled, it delegates the decision and teardown to the security-agent module.

Every detected product is assigned one of five fail-closed classifications:

  • ApprovedHealthy — the product is explicitly listed in ApprovedEndpointSecurityProducts and every required health check passes. It remains installed and provisioning may continue.
  • ApprovedMisconfigured — the product is approved to remain, but a conclusive health check finds it unhealthy. It is removed so the approved product can be re-installed cleanly by the external management system.
  • Unauthorized — detection is conclusive, the configured approved list is non-empty, and the supported product is not approved to remain. It becomes a removal target.
  • Unsupported — TechWizard detects endpoint security that its configured teardown path cannot safely handle, including enterprise McAfee/Trellix overlap. It is not removed and later provisioning phases are blocked.
  • Inconclusive — approval, detection, or health cannot be established safely. It is never removed implicitly and later provisioning phases are blocked.

Approval alone is not a health result. For an approved product, validation requires Windows SecurityCenter2 to report real-time protection enabled and definitions current; configured vendor services to be present and running (and Automatic when required); expected install-directory and registry integrity; driver-service registration where applicable; and configured definition-age and minimum-version floors. ConsoleVerification can additionally require a verified external vendor/RMM probe to confirm console connectivity or enrollment. Inventory and analysis output reports only the existing sanitized evidence categories and health reason codes; it does not expose paths, command lines, artifact metadata, or private values.

The lifecycle is configured through an external security-agents.psd1 overlay:

  • ApprovedEndpointSecurityProducts is the explicit list of products allowed to remain when healthy. An empty list is fail-closed: detected products become Inconclusive, not implicitly unauthorized, and are not removed.
  • HealthPolicy supplies each approved product's RequiredServices, RequireAutomaticStart, MaxDefinitionAgeDays, and MinimumVersion. Missing, incomplete, or invalid policy data makes health Inconclusive.
  • ConsoleVerification optionally enables a no-argument, externally supplied and verified enrollment/connectivity probe using Enabled, ArtifactId, and TimeoutSeconds. Disabled verification is optional; enabled but incomplete, unavailable, timed-out, or failed verification makes health Inconclusive. URLs, hashes, signers, tokens, credentials, and client-specific metadata stay in external overlays or the client-artifacts catalog and are not committed to this repository.

Security Center and Add/Remove Programs probes are mandatory for a conclusive inventory. If either probe is unavailable, incomplete, or errors—or if an enabled console verification probe cannot complete—the affected detection is Inconclusive and cannot authorize removal. Configuration overlays may only narrow the built-in ESET/McAfee artifact catalog; the UnsupportedUninstallPatterns, UnsupportedServices, and UnsupportedPaths refusal rules remain immutable.

For supported removal, ESET and consumer McAfee use the product's registered silent uninstaller when available, followed by catalog-constrained service, driver, directory, registry, and Security Center cleanup using in-box Windows facilities. The tool does not bundle or require ESETUninstaller.exe or MCPR. On attended runs, destructive removal always requires a dangerous, default-No confirmation that -Force cannot bypass, and mutation remains behind ShouldProcess. If teardown fails or leaves unexplained evidence, product metadata is preserved for retry and later provisioning phases remain blocked. If known artifacts are staged for boot-time deletion, reboot/resume completes and verifies teardown before provisioning continues.

SentinelOne remains detection-only in the native engine. TechWizard does not apply the ESET/McAfee teardown primitives to it or bypass vendor authorization. A separate, disabled-by-default adapter may invoke only the verified official vendor cleaner when complete metadata is supplied externally through the security overlay and client-artifacts catalog. Missing or invalid adapter data fails closed.

The provisioning order is an explicit contract: SecurityAgents runs first, Resolve-TechToolsPhaseOrder keeps Debloat before Apps, and only ApprovedHealthy retention or successfully verified teardown permits those later phases to run. A removed ApprovedMisconfigured product records an external re-install handoff; deployment or re-enrollment of approved endpoint security remains the responsibility of external RMM/MDM tooling, not TechWizard.

Common Examples

Run workstation repair in automatic mode (the default). Repair-Workstation, Prepare-System, and Factory-Reset default to Phase = Auto: they first perform a read-only analysis of the operating system — including Event Logs, image health, device-driver problems, pending reboot, free disk space, profile corruption, RMM agent health, OEM, bloatware, required tools, UI defaults, domain/Entra-join state, and (for Factory-Reset) the non-whitelisted app removal plan, break-glass administrator state, and the account/profile cleanup plan — print a report, and then run only the phases whose goal is not already satisfied, in the canonical dependency order. When a probe is inconclusive the phase still runs, so analysis never silently skips needed work. Use Phase = 'All' to force every selectable phase, or name individual phases (Repair, Updates, Drivers, Profile, Cleanup, RMMAgent) to run exactly those. The deep Event Viewer analysis runs only as part of Repair-Workstation's Auto; it is not selectable by name and All does not run it.

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Repair-Workstation

Force every repair phase regardless of analysis:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Repair-Workstation `
    -ToolArgs @{ Phase = 'All' }

Run only updates and cleanup:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Repair-Workstation `
    -ToolArgs @{ Phase = @('Updates', 'Cleanup') }

Prepare a workstation, including debloat and UI standardization:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Prepare-System `
    -ToolArgs @{ Phase = @('Debloat', 'Apps', 'UI') }

Customize the Microsoft 365 app set on one machine — drop Publisher and Access, add OneNote — without prompts (unattended changes require naming the apps; force mode alone never removes anything):

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Set-Microsoft365Apps `
    -ToolArgs @{ RemoveApps = @('Publisher', 'Access'); AddApps = @('OneNote'); Force = $true }

Run it with no arguments for an interactive review of the current per-app state and add/remove menus; -ToolArgs @{ StatusOnly = $true } reports the state and changes nothing.

Inventory stale Active Directory objects without making any changes (run on a domain controller or RSAT-equipped admin workstation):

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Clean-ADStaleObjects `
    -ToolArgs @{ Phase = @('Scan', 'Report') }

The full pipeline disables then quarantines stale objects; permanent deletion is opt-in and only runs with AllowHardDelete:

& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Clean-ADStaleObjects `
    -ToolArgs @{ Phase = @('All'); AllowHardDelete = $true }

Discover and classify the devices on the local network (auto-detected) with a standard scan — installs nmap on demand and writes CSV/JSON/HTML inventories under C:\TechWizard\Logs\Find-NetworkAssets:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Find-NetworkAssets

Scan a specific subnet thoroughly and skip all prompts (Force authorizes the scan and accepts the on-demand nmap install):

& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Find-NetworkAssets `
    -ToolArgs @{ Target = '192.168.10.0/24'; Profile = 'Thorough'; Force = $true }

Fast host-discovery sweep of two subnets (host list + MAC/vendor, no port scan):

& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) `
    -RepoBaseUrl $RepoBaseUrl `
    -Tool Find-NetworkAssets `
    -ToolArgs @{ Target = '10.0.0.0/24 10.0.1.0/24'; Profile = 'Discovery' }

Debloat Coverage (All Accounts, Aggressive)

The Debloat phase removes detected UWP and Win32 bloat with the coverage of an aggressive "scan all Windows accounts" uninstaller pass:

  • AppX/UWP: matching packages are removed for every user account (Remove-AppxPackage -AllUsers) and deprovisioned so new users never get them; leftover per-user AppData\Local\Packages\<family> state folders for removed families are scrubbed across all profiles. An explicit target profile keeps removal scoped to that one account.
  • Win32: the Uninstall hives of the machine, every logged-on user, and — by default — every offline profile (their NTUSER.DAT is loaded for the pass and unloaded afterwards) are enumerated. Silent uninstall is attempted first (MSI /qn, QuietUninstallString, optional winget fallback); after a successful uninstall, remnants (orphaned Uninstall key, leftover install directory, dead Start Menu shortcuts) are cleaned. When no silent uninstaller exists or it fails, the program is force-removed (its services stopped, disabled, and deregistered; its processes stopped; its install directory deleted within approved roots — falling back to the uninstaller's own directory when the entry records no install location; its Uninstall key and shortcuts removed) — confirmed once per run as a dangerous action, auto-approved only in force/unattended mode. Locked or ACL-protected leftovers escalate automatically: ownership/ACL reset and retry, then per-item deletion, and finally reboot-time deletion via the Windows pending-file-rename mechanism, which runs at early boot before any service can re-lock its files. The Uninstall registry entry is never deleted while a program's files remain un-handled (unless its own uninstaller already ran), so the official uninstall path always stays available.

Every safety layer still applies: the essential AppX and Win32 allowlists, the publisher allowlist, the SystemComponent guard, product-wide sibling protection, the RMM no-touch policy, and a strict approved-deletion-root check that refuses to delete anything outside Program Files, Program Files (x86), ProgramData, or a profile's AppData (and never OS-owned subtrees such as Windows, WindowsApps, Windows Defender, or ProgramData\Microsoft). The toggles live in config/debloat-settings.psd1 (AppxRemoveAllUsers, AppxRemoveLeftoverData, Win32ScanAllUserProfiles, Win32LeftoverCleanup, Win32ForcedRemovalFallback), all enabled by default.

Local Checkout

git clone https://git.ds.reinitialized.net/reinitialized.net/TechWizard.git
cd TechWizard
powershell -ExecutionPolicy Bypass -File .\start.ps1

Launch a specific local tool:

powershell -ExecutionPolicy Bypass -File .\start.ps1 -Tool Repair-Workstation

Requirements

  • Run from an elevated PowerShell session.
  • Target runtime is Windows PowerShell 5.1, which ships in-box with every supported build of Windows. No separate PowerShell runtime is downloaded or installed; start.ps1 runs directly under the host shell.
  • TechWizard runs on every platform that supports Windows PowerShell 5.1 — Windows 7 SP1 / Server 2008 R2 (via WMF 5.1) through current Windows 11 / Server 2025. Features tied to a newer NT release (AppX removal, DISM component-store repair, winget, pnputil device rescans, Entra join, Windows Hello, Web sign-in, local-account cmdlets, Windows 11 taskbar alignment) are gated by release feature flags resolved during the read-only analysis pass: on an older release each gated step is skipped with a warning (or fails loudly up front when the work is required), and the analysis report lists which features the host lacks. Nothing hard-fails mid-phase because the OS predates a feature.
  • Target workstations must be able to reach https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/indev.
  • If the Forgejo repository is private, use a local checkout or expose a read-only raw URL reachable by the workstation before launching remotely.

Branches And Overrides

The examples above use the indev branch. To launch another branch, change the branch segment in RepoBaseUrl:

Set-ExecutionPolicy Bypass -Scope Process -Force
$RepoBaseUrl = 'https://git.ds.reinitialized.net/reinitialized.net/TechWizard/raw/branch/main'
& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) -RepoBaseUrl $RepoBaseUrl

-RepoBaseUrl is intentionally included in the remote commands so every downloaded script, module, and config file comes from the same Forgejo branch.

Version Banner

Every launch prints a banner naming the product version, branch, and running commit, then compares the running commit to the branch tip via the Forgejo commits API:

  • Local checkout: the running commit is read from .git and compared to the branch tip. A warning is printed when the checkout is behind.
  • Remote irm/iex launch: there is no .git directory. When every bootstrap module was freshly downloaded, the running code is the branch tip by construction; the tip SHA is adopted, reported, and stamped into the module cache (commit.json in the cache root). When a later launch cannot reach the repository and falls back to cached modules, that stamp names the running commit. A cached snapshot that was validated against the branch tip is reported as up to date; only a cache that is behind, or that could not be validated, is reported as a warning. The check is best-effort and never blocks a launch: with no network and no stamp, the banner says the version could not be verified.

Client Configuration Overlays

Org- and client-specific values — real RMM SERVERADDRESS/SERVERPASS, the managed ScreenConnect ExpectedInstanceHost/ExpectedInstanceId, location ids — are secrets and must never be committed to this repository. They live in an external config root (a mapped work Google Drive letter, a UNC share, or the local drop C:\TechWizard\client-config) with this layout:

<root>\generic\rmm-agent.psd1                  org-wide overrides
<root>\clients\AcmeCorp\rmm-agent.psd1         per-client overrides

Overlay files mirror the repo's config/*.psd1 names and contain only the keys being overridden; they are deep-merged over the repo defaults (generic first, then the selected client) every time a config file is loaded, so all tools pick them up automatically. Scalars and arrays in an overlay replace the base value; nested hashtables merge.

Select the root and client at launch:

& ([scriptblock]::Create((irm "$RepoBaseUrl/start.ps1"))) -RepoBaseUrl $RepoBaseUrl `
    -ClientConfigPath 'G:\TechWizard' -Client 'AcmeCorp'

Example G:\TechWizard\generic\rmm-agent.psd1 overlay that fills in the real Automate install values and pins the managed ScreenConnect instance without touching the repo:

@{
    Agents = @{
        Automate = @{
            InstallArgs = @{
                SERVERADDRESS = 'https://automate.example.com'
                SERVERPASS    = 'RealEncryptedServerPassword'
                LOCATION      = '42'
            }
            RequiredComponents = @(
                @{
                    DisplayName          = 'Managed ScreenConnect Access Agent'
                    Type                 = 'ScreenConnect'
                    ServiceNamePattern   = 'ScreenConnect Client*'
                    RequiredRole         = 'Access'
                    ExpectedInstanceHost = 'instance-abc123.screenconnect.example.com'
                    ExpectedInstanceId   = ''
                }
            )
        }
    }
}

Notes:

  • Only a pointer (root path + client name) is persisted locally in C:\TechWizard\client-context.json so reboot/resume finds the same context; secret values are read from the external root at load time and are never copied there in cleartext. A run that reboots does persist the secrets it already resolved to C:\TechWizard\resume-secrets.json, DPAPI-protected and ACL'd to SYSTEM plus Administrators, so the resumed run can finish; that file is removed with the rest of the resume state by Remove-ResumeState.
  • A per-user mapped drive letter may be absent in a resumed session; prefer a UNC path, or copy the overlays to C:\TechWizard\client-config for runs that reboot. RMM install values resolved before a reboot are already carried through resume by the existing runtime-value capture.
  • A configured-but-unreachable root logs a warning and the run continues on repo defaults; RMM readiness checks still fail loudly on unresolved placeholders, so a lost overlay cannot silently install with dummy values.
  • Access to the overlay store is governed by the drive/share ACLs; keep the root readable only by technicians.
  • Overlays are a convenience, not a requirement: on an attended run without an overlay (an independent run), Prepare-System keeps the RMM phase in its Auto plan, asks which supported RMM agent to install when more than one is configured, prompts for the missing install values, and carries both the choice and the values through reboot resume. Unattended runs without resolvable values still skip an optional agent (and fail loudly on a required one).

Logs And Resume

TechWizard writes logs, downloads, backups, and reboot resume state under C:\TechWizard\. Tools that require a reboot save resume state and relaunch through start.ps1 after Windows restarts.

The default unattended resume path writes C:\TechWizard\resume-state.json, writes C:\TechWizard\resume.ps1, and registers the startup scheduled task TechToolsResumeAsSystem as NT AUTHORITY\SYSTEM. This is intended for unattended/session-0 resume and can be visible in RMM Backstage when the RMM exposes session 0.

When Prepare-System must reboot after domain/Entra join and the active RMM agent cannot be verified, TechWizard requests the visible-console fallback instead: it creates a temporary local administrator, configures one AutoAdminLogon, registers TechToolsResumeOnTempAdminLogon, clears the AutoAdminLogon password as soon as the bootstrap starts, and cleans up the temporary account after the resumed run.

Before arming AutoAdminLogon, TechWizard temporarily neutralizes the settings that make Windows silently ignore it — the Windows 11 "require Windows Hello sign-in" enforcement (DevicePasswordLessBuildVersion) and any legal-notice sign-in banner — recording the originals in C:\TechWizard\autologon-blockers.json and restoring them when the resume starts (or on teardown/failure recovery). The armed Winlogon values are read back and verified; if arming cannot be verified the reboot is refused instead of stranding the machine. AutoAdminLogon is armed with an AutoLogonCount of 3 (not 1) because Windows Update servicing can consume auto-logon counts on intermediate boot transitions; the bootstrap clears all remaining auto-logon state the moment it runs, so no surplus logon ever fires. Every resume-carrying auto-logon arming also registers TechToolsResumeWatchdog, a SYSTEM startup task delayed 10 minutes past boot: if the interactive auto-logon never signs in (GPO banner re-applied, sign-in blocked by policy), the watchdog picks the run up — and when the resume was armed for a visible temporary-admin session, it first RE-ARMS the auto-logon (fresh password, blockers re-suspended) and reboots so the run comes back on the visible console; only after the re-arm attempt cap (2) does it fall back to resuming headless in session 0, so a blocked logon can no longer strand a half-provisioned machine at the sign-in screen.

If the auto-logon fails and a technician signs into a DIFFERENT admin account and relaunches TechWizard, the pending resume is no longer silently adopted by that account: the launcher detects the mismatch and offers to sign the technician out and hand the run back to the TechWizard temporary account (Enter declines and continues the resume in the current session instead). If the resume is already running live in another session (for example the SYSTEM watchdog picked it up), a relaunch reports where it is running instead of starting a second copy. Re-launching with -CancelResume still abandons a pending resume entirely.

Manual resume validation checklist:

  1. Trigger a controlled reboot-required condition or mock the resume handoff.
  2. Before reboot, verify Get-ScheduledTask -TaskName TechToolsResumeAsSystem, Test-Path C:\TechWizard\resume-state.json, and Test-Path C:\TechWizard\resume.ps1.
  3. Reboot and do not log in.
  4. From RMM Backstage/session 0, verify a powershell process starts and the new log contains Resuming previous TechTools session.
  5. Verify the remaining phases run and cleanup removes resume-state.json, resume.ps1, and the scheduled task after success.

Visible-console fallback validation:

  1. Trigger a domain/Entra reboot handoff without a healthy active RMM agent.
  2. Before reboot, verify C:\TechWizard\temp-admin.json, C:\TechWizard\resume-state.json, C:\TechWizard\resume.ps1, TechToolsResumeOnTempAdminLogon, and the one-time Winlogon AutoAdminLogon values.
  3. After reboot, verify the temporary administrator signs in, a visible PowerShell console resumes TechWizard, and the new log contains Resuming previous TechTools session.
  4. Verify cleanup removes the resume files, scheduled tasks, Winlogon password, and temporary administrator.

Phase Outcomes And Retry Policy

Every phase of a multi-phase tool reports one canonical outcome. The outcome decides whether the phase is retried, whether the run continues, and what the technician is told — so the vocabulary distinguishes why a phase did not succeed, not merely that it didn't.

Outcome Meaning Retried?
Completed The phase goal was achieved.
CompletedWithWarnings Goal achieved; something optional was skipped or degraded.
Skipped Nothing to do, or an earlier critical phase stopped it.
Deferred A precondition this run can satisfy itself is unmet — most often a pending reboot ahead of an MSI install. Yes, after the reboot.
Blocked A deterministic condition outside the run's control is unmet. Re-running unattended produces the identical result. Carries an operator remedy. No.
Failed The goal failed for a reason that may be transient. Yes, up to the attempt limit.
RebootInitiated The phase armed a reboot and handed off.
Unverified The phase returned nothing a canonical outcome could be read from. Any unrecognised status grades here. No.

Blocked and Deferred are not completions and never count toward the session's completed phases.

Bounded retries

C:\TechWizard\resume-state.json carries a per-phase attempt ledger. A Failed phase is retried after the next reboot; once it has spent 2 attempts it converts to Blocked, stops being the resume continuation point, and the run proceeds through its remaining phases instead of retrying it forever.

This exists because a deterministic environmental failure previously retried without limit. A real provisioning session met a client network doing TLS inspection, which broke every winget install; the Apps phase failed and was re-queued on every following reboot. A failed phase cannot arm a reboot itself, so it rode along on other phases' reboots — six reboots and three identical failures, ending only because the last run happened to contain no phase that requested a seventh. A blocked phase now states its remedy once and gets out of the way.

A global reboot budget (12 automatic reboots per session, also tracked in the resume state) is the outer backstop. It is a runaway guard rather than a schedule, so it sits well above the worst legitimate run; when it is exhausted TechWizard refuses to arm another reboot and names the phases still outstanding.

Preconditions

Phases that drive MSI installs — Apps and RMMAgent — do not start while a reboot is pending. Windows Installer fails such installs with the generic fatal error 1603 (MsiSystemRebootPending=1), which previously looked like a broken installer or resident security software. They now report Deferred, take one reboot, and run cleanly.

Reading the summary

The execution summary reports each outcome as its own bucket, separates the current run from the whole session, and always prints the remedy for a blocked phase:

  Apps         : Blocked: winget cannot verify its source's pinned TLS certificate
               Remedy: SSL/TLS inspection on this network breaks the winget source.
               Exempt the winget CDN from inspection, or supply DownloadURL
               fallbacks for the required tools, then re-run -Phase Apps.

Completed phases (this run): Updates, Debloat. Completed with warnings: none.
Blocked phases: Apps. Deferred phases: none. Failed phases: none.
Skipped phases: none. Completed phases (session total): SecurityAgents, Updates,
Debloat, UI.

Earlier versions derived the summary only from the current run's phase table, so the final run of a multi-reboot session could report "Completed phases: none" after five phases had in fact completed in earlier runs. A hard RMM install failure was also reported under "Completed phases", because CompletedWithWarnings was folded into that bucket.

Required tools

Required in config/required-tools.psd1 decides whether a tool's absence is a phase failure. The shipped baseline marks Microsoft Edge, 7-Zip, Adobe Acrobat Reader and VLC as required, along with Microsoft 365 (config/microsoft-365.psd1) and the RMM agent (config/rmm-agent.psd1). Redistributables, .NET runtimes, Temurin JREs and Zoom stay optional.

A required tool that cannot be installed for an environmental reason — a proxy breaking the package source, no network — reports Blocked, not Failed: retrying on the same network cannot succeed, so the run reports the remedy and continues. Only a genuine, non-environmental failure of a required tool fails the phase.

Resume state schema

resume-state.json is versioned (SchemaVersion) and carries a RunId identifying one logical provisioning session across all of its reboots. State written by a newer build than the one reading it is refused rather than guessed at field by field. The completed-phase history is matched on RunId; it previously relied on an exact ordered match of the saved phase list, so any change to the phase set silently discarded the whole session history.

Domain join targets

The -OUPath target is structurally checked during the initial preflight. On a workgroup machine the directory bind may remain inconclusive until the join credential is available; TechWizard says so explicitly, then validates the target with that credential before calling Add-Computer. An OU or container proved not to exist reports Blocked with the exact remedy instead of failing inside Add-Computer with The system cannot find the file specified (0x2), which is also mapped to an actionable diagnosis.

When a technician is at the console, an invalid target opens the directory browser instead so the correct destination can be selected. The browser lists both organizational units and containers — CN=Computers is the most common legitimate target and was previously unselectable — and shows each entry's object class. TechWizard never silently substitutes the domain's default computer container.