Add files via upload

This commit is contained in:
Daniel Card
2026-07-05 05:58:24 +01:00
committed by GitHub
parent 346ce56252
commit 2c52770008
2 changed files with 115 additions and 35 deletions
+76 -32
View File
@@ -29,8 +29,18 @@
restore the true Windows default (absent), so the Settings UI
is not left in a "managed by your organization" state.
User mode:
-UserMode restricts the tool to per-user (HKCU) items only - the ones
that need NO administrator rights. Run it as your normal (unelevated)
account for personal privacy hardening: it writes only YOUR user hive,
so it also avoids the "HKCU points at the admin's profile when you
elevate as a different user" pitfall. HKLM policy/service/task items
are hidden in this mode.
Usage :
.\Manage-WindowsTelemetry.ps1 # interactive menu
.\Manage-WindowsTelemetry.ps1 # interactive menu (all items)
.\Manage-WindowsTelemetry.ps1 -UserMode # per-user items only, no admin
.\Manage-WindowsTelemetry.ps1 -UserMode -DisableAll # harden your user profile
.\Manage-WindowsTelemetry.ps1 -Report # print status and exit
.\Manage-WindowsTelemetry.ps1 -DisableAll # turn telemetry OFF (keeps [SEC] ON)
.\Manage-WindowsTelemetry.ps1 -DisableAll -IncludeSecurity # also disable SmartScreen
@@ -48,6 +58,7 @@ param(
[switch]$DisableAll,
[switch]$EnableAll,
[switch]$IncludeSecurity, # also disable [SEC] SmartScreen features in bulk actions
[switch]$UserMode, # only per-user (HKCU) items; no admin needed
[string]$Csv
)
@@ -64,6 +75,7 @@ function Test-IsAdmin {
}
$Script:IsAdmin = Test-IsAdmin
$Script:UserMode = [bool]$UserMode
# ---------------------------------------------------------------------------
# Registry helpers
@@ -531,6 +543,15 @@ function Get-Controls {
return $c
}
# Restrict to per-user (HKCU, no-admin) items when in user mode.
function Select-ActiveControls {
param($All)
if ($Script:UserMode) {
return @($All | Where-Object { -not $_.AdminReq })
}
return $All
}
# ---------------------------------------------------------------------------
# Display
# ---------------------------------------------------------------------------
@@ -549,13 +570,18 @@ function Show-Status {
Write-Host '==================================================================' -ForegroundColor Cyan
Write-Host ' Windows 11 Telemetry / Diagnostic Data Status' -ForegroundColor Cyan
Write-Host (' Host: {0} Admin: {1} {2}' -f $env:COMPUTERNAME, $Script:IsAdmin, (Get-Date)) -ForegroundColor DarkCyan
if ($Script:UserMode) {
Write-Host ' MODE: USER (per-user HKCU items only; no admin required)' -ForegroundColor Magenta
} else {
Write-Host ' MODE: FULL (per-user + system-wide items)' -ForegroundColor DarkCyan
}
Write-Host ' Enabled = collecting/on Disabled = hardened/off' -ForegroundColor DarkCyan
Write-Host '==================================================================' -ForegroundColor Cyan
Write-Host ('{0,-4}{1,-36}{2,-18}{3}' -f '#', 'Setting', 'Category', 'State') -ForegroundColor White
Write-Host ('{0,-4}{1,-36}{2,-18}{3}' -f '---', '-------', '--------', '-----') -ForegroundColor DarkGray
$i = 0
$nEnabled = 0; $nDisabled = 0; $nAbsent = 0; $nSecOff = 0
$nEnabled = 0; $nDisabled = 0; $nAbsent = 0; $nSecOff = 0; $nSec = 0; $anyLock = $false
foreach ($ctrl in $Controls) {
$i++
$state = Get-ControlState -Ctrl $ctrl
@@ -564,22 +590,24 @@ function Show-Status {
elseif ($state -like 'Not present*') { $nAbsent++ }
$sec = ''
if ($ctrl.Security) {
$sec = ' [SEC]'
$sec = ' [SEC]'; $nSec++
if ($state -like 'Disabled*') { $nSecOff++ }
}
$lock = ''
if ($ctrl.AdminReq -and -not $Script:IsAdmin) { $lock = ' *' }
if ($ctrl.AdminReq -and -not $Script:IsAdmin) { $lock = ' *'; $anyLock = $true }
$line = ('{0,-4}{1,-36}{2,-18}' -f $i, ($ctrl.Name + $sec), $ctrl.Category)
Write-Host $line -NoNewline
Write-Host ($state + $lock) -ForegroundColor (Get-StateColor $state)
}
Write-Host ('{0,-4}{1,-36}{2,-18}{3}' -f '---', '-------', '--------', '-----') -ForegroundColor DarkGray
Write-Host (' Summary: {0} enabled, {1} disabled, {2} not present' -f $nEnabled, $nDisabled, $nAbsent) -ForegroundColor White
if ($nSec -gt 0) {
Write-Host ' [SEC] = anti-malware reputation check. Disabling REDUCES protection' -ForegroundColor DarkYellow
}
if ($nSecOff -gt 0) {
Write-Host (' WARNING: {0} security SmartScreen feature(s) are currently OFF' -f $nSecOff) -ForegroundColor Red
}
if (-not $Script:IsAdmin) {
if ($anyLock) {
Write-Host ' * requires Administrator to change (run elevated)' -ForegroundColor DarkYellow
}
Write-Host ''
@@ -653,16 +681,22 @@ function Invoke-AllAction {
# Interactive menu
# ---------------------------------------------------------------------------
function Start-Menu {
param($Controls)
param($Controls) # full catalog; the active view is filtered by user mode
while ($true) {
Show-Status -Controls $Controls
$view = @(Select-ActiveControls -All $Controls)
Show-Status -Controls $view
Write-Host 'Commands:' -ForegroundColor White
Write-Host ' <n> toggle item n (Enable<->Disable)'
Write-Host ' e <n> enable item n'
Write-Host ' d <n> disable item n'
Write-Host ' D disable ALL (harden; keeps [SEC] SmartScreen ON)'
Write-Host ' E enable ALL (restore Windows default)'
Write-Host ' D disable ALL shown (harden; keeps [SEC] SmartScreen ON)'
Write-Host ' E enable ALL shown (restore Windows default)'
Write-Host ' S disable ALL [SEC] SmartScreen features (reduces security)'
if ($Script:UserMode) {
Write-Host ' m switch to FULL mode (also show system-wide items)'
} else {
Write-Host ' m switch to USER mode (per-user items only, no admin)'
}
Write-Host ' r refresh view'
Write-Host ' c <path> export status to CSV'
Write-Host ' q quit'
@@ -675,22 +709,23 @@ function Start-Menu {
switch -Regex -CaseSensitive ($inp) {
'^[Qq]$' { return }
'^[Rr]$' { continue }
'^[Mm]$' { $Script:UserMode = -not $Script:UserMode; continue }
'^D$' {
if ((Read-Host 'Disable ALL telemetry? type YES') -ceq 'YES') {
Invoke-AllAction -Controls $Controls -Action Disable
if ((Read-Host 'Disable ALL shown telemetry? type YES') -ceq 'YES') {
Invoke-AllAction -Controls $view -Action Disable
}
Read-Host 'Press Enter'; continue
}
'^E$' {
if ((Read-Host 'Enable ALL (Windows default)? type YES') -ceq 'YES') {
Invoke-AllAction -Controls $Controls -Action Enable
if ((Read-Host 'Enable ALL shown (Windows default)? type YES') -ceq 'YES') {
Invoke-AllAction -Controls $view -Action Enable
}
Read-Host 'Press Enter'; continue
}
'^S$' {
$secList = @($Controls | Where-Object { $_.Security })
$secList = @($view | Where-Object { $_.Security })
if ($secList.Count -eq 0) {
Write-Host 'No [SEC] controls in the catalog.' -ForegroundColor DarkYellow
Write-Host 'No [SEC] controls shown (they are system-wide; switch to FULL mode with "m").' -ForegroundColor DarkYellow
Read-Host 'Press Enter'; continue
}
Write-Host ''
@@ -703,32 +738,32 @@ function Start-Menu {
Read-Host 'Press Enter'; continue
}
'^[Cc]\s+(.+)$' {
Export-StatusCsv -Controls $Controls -Path $Matches[1].Trim('"')
Export-StatusCsv -Controls $view -Path $Matches[1].Trim('"')
Read-Host 'Press Enter'; continue
}
'^[Ee]\s+(\d+)$' {
$n = [int]$Matches[1]
if ($n -ge 1 -and $n -le $Controls.Count) { Invoke-ControlAction -Ctrl $Controls[$n-1] -Action Enable }
if ($n -ge 1 -and $n -le $view.Count) { Invoke-ControlAction -Ctrl $view[$n-1] -Action Enable }
else { Write-Host 'Out of range' -ForegroundColor Red }
Read-Host 'Press Enter'; continue
}
'^[Dd]\s+(\d+)$' {
$n = [int]$Matches[1]
if ($n -ge 1 -and $n -le $Controls.Count) { Invoke-ControlAction -Ctrl $Controls[$n-1] -Action Disable }
if ($n -ge 1 -and $n -le $view.Count) { Invoke-ControlAction -Ctrl $view[$n-1] -Action Disable }
else { Write-Host 'Out of range' -ForegroundColor Red }
Read-Host 'Press Enter'; continue
}
'^\d+$' {
$n = [int]$inp
if ($n -ge 1 -and $n -le $Controls.Count) {
$ctrl = $Controls[$n-1]
if ($n -ge 1 -and $n -le $view.Count) {
$ctrl = $view[$n-1]
$state = Get-ControlState -Ctrl $ctrl
if ($state -like 'Enabled*') { Invoke-ControlAction -Ctrl $ctrl -Action Disable }
else { Invoke-ControlAction -Ctrl $ctrl -Action Enable }
} else { Write-Host 'Out of range' -ForegroundColor Red }
Read-Host 'Press Enter'; continue
}
default { Write-Host 'Unknown command (d/e need an item number; D/E/S alone act on ALL)' -ForegroundColor Red; Start-Sleep -Milliseconds 600 }
default { Write-Host 'Unknown command (d/e need an item number; D/E/S/m act on the view)' -ForegroundColor Red; Start-Sleep -Milliseconds 600 }
}
}
}
@@ -737,34 +772,43 @@ function Start-Menu {
# Main
# ---------------------------------------------------------------------------
$controls = Get-Controls
$active = @(Select-ActiveControls -All $controls)
if ($IncludeSecurity -and -not $DisableAll) {
Write-Host 'NOTE: -IncludeSecurity only has an effect together with -DisableAll; ignoring it.' -ForegroundColor DarkYellow
}
if ($UserMode) {
Write-Host ('USER MODE: showing {0} per-user item(s) only (no admin needed).' -f $active.Count) -ForegroundColor Magenta
}
if ($DisableAll) {
Invoke-AllAction -Controls $controls -Action Disable -WithSecurity:$IncludeSecurity
Show-Status -Controls $controls
if ($Csv) { Export-StatusCsv -Controls $controls -Path $Csv }
Invoke-AllAction -Controls $active -Action Disable -WithSecurity:$IncludeSecurity
Show-Status -Controls $active
if ($Csv) { Export-StatusCsv -Controls $active -Path $Csv }
return
}
if ($EnableAll) {
Invoke-AllAction -Controls $controls -Action Enable
Show-Status -Controls $controls
if ($Csv) { Export-StatusCsv -Controls $controls -Path $Csv }
Invoke-AllAction -Controls $active -Action Enable
Show-Status -Controls $active
if ($Csv) { Export-StatusCsv -Controls $active -Path $Csv }
return
}
if ($Report -or $Csv) {
if ($Report) { Show-Status -Controls $controls }
if ($Csv) { Export-StatusCsv -Controls $controls -Path $Csv }
if ($Report) { Show-Status -Controls $active }
if ($Csv) { Export-StatusCsv -Controls $active -Path $Csv }
return
}
if (-not $Script:IsAdmin) {
if ($UserMode) {
Write-Host ''
Write-Host 'USER MODE is on: changes apply to YOUR account only and need no' -ForegroundColor Magenta
Write-Host 'elevation. Press "m" in the menu to include system-wide items.' -ForegroundColor Magenta
} elseif (-not $Script:IsAdmin) {
Write-Host ''
Write-Host 'NOTE: Not running as Administrator. HKLM / service / task items' -ForegroundColor DarkYellow
Write-Host ' will show as read-only (*) and cannot be changed until you' -ForegroundColor DarkYellow
Write-Host ' relaunch this script in an elevated PowerShell window.' -ForegroundColor DarkYellow
Write-Host ' show as read-only (*). Use -UserMode (or "m") to work with' -ForegroundColor DarkYellow
Write-Host ' per-user items only, or relaunch elevated for the rest.' -ForegroundColor DarkYellow
}
# Start-Menu always receives the full catalog; user mode filters the view.
Start-Menu -Controls $controls
+37 -1
View File
@@ -68,6 +68,11 @@ services and scheduled tasks** from one place.
# Interactive menu (run from an ELEVATED PowerShell to change HKLM/services/tasks)
.\Manage-WindowsTelemetry.ps1
# USER MODE - per-user (HKCU) items only, NO admin needed. Run as yourself.
.\Manage-WindowsTelemetry.ps1 -UserMode
.\Manage-WindowsTelemetry.ps1 -UserMode -DisableAll # harden your profile
.\Manage-WindowsTelemetry.ps1 -UserMode -Report
# One-shot hardening: turn all telemetry OFF (keeps [SEC] SmartScreen ON)
.\Manage-WindowsTelemetry.ps1 -DisableAll
@@ -111,14 +116,45 @@ Two design rules worth knowing:
= Automatic, `dmwappushservice` / `WerSvc` = Manual), not blanket
Automatic.
## User mode (`-UserMode`) - recommended for personal use
For personal privacy/telemetry hardening, run **user mode** as your normal
(unelevated) account:
```powershell
.\Manage-WindowsTelemetry.ps1 -UserMode
```
User mode shows **only the per-user (HKCU) items** - Advertising ID, tailored
experiences, inking/typing, feedback frequency, search suggestions,
Suggestions/Ads, Windows Copilot, and the Store-apps SmartScreen check. All
of these change **your account only** and need **no administrator rights**.
Why it's the safer choice for a single-user machine:
- **No elevation, no hive mix-up.** System-wide (HKLM) items require admin,
and the usual way to get admin is to elevate. But if you elevate using a
*different* admin account, `HKCU` inside that elevated session points at the
**admin's** profile - so per-user toggles silently apply to the wrong user.
Running user mode unelevated as yourself writes your own hive, every time.
- **Nothing you can't set from the Settings app** - it's the same per-user
switches, just scripted and repeatable.
The header shows `MODE: USER` or `MODE: FULL`. In the interactive menu press
**`m`** to switch between them at any time; `-DisableAll` / `-EnableAll` /
`-Report` / `-Csv` all respect the mode. To also harden system-wide items
(diagnostic data, DiagTrack, scheduled tasks, etc.), run **without**
`-UserMode` from an elevated PowerShell.
## Interactive menu commands
| Command | Action |
|---|---|
| `<n>` | Toggle item *n* (Enabled <-> Disabled) |
| `e <n>` / `d <n>` | Enable / disable item *n* |
| `E` / `D` (uppercase) | Enable / disable **ALL** items (asks for `YES` confirmation; `D` keeps `[SEC]` items ON) |
| `E` / `D` (uppercase) | Enable / disable **ALL** shown items (asks for `YES` confirmation; `D` keeps `[SEC]` items ON) |
| `S` | Disable the `[SEC]` SmartScreen features (requires typing `DISABLE-SECURITY`) |
| `m` | Toggle between USER mode (per-user only) and FULL mode (all items) |
| `r` | Refresh the view |
| `c <path>` | Export status to CSV |
| `q` | Quit |