Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ A lightweight, open-source toolkit to disable Windows telemetry and improve priv
- ⏪ Rollback support for most modules
- 💾 System restore point creation
- 🖥️ Interactive and batch modes
- 📊 Audit logging to Windows Event Log
- 🔄 Script update checker
- 🛡️ Integrity checking for modules (file size and modification time)

## 🚀 Quick Start

Expand All @@ -40,21 +43,6 @@ A lightweight, open-source toolkit to disable Windows telemetry and improve priv
.\run.bat
```

### Command Line Options
```powershell
# Run all modules
.\windows-telemetry-blocker.ps1 -all

# Run specific modules
.\windows-telemetry-blocker.ps1 -modules telemetry,services

# Interactive mode
.\windows-telemetry-blocker.ps1 -interactive

# Advanced options
powershell -ExecutionPolicy Bypass -File windows-telemetry-blocker.ps1 -all -dryrun -verbose -rollbackOnFailure
```

## 🧩 Modules

| Module | Description |
Expand Down
20 changes: 14 additions & 6 deletions run.bat
Original file line number Diff line number Diff line change
Expand Up @@ -89,22 +89,30 @@ echo Please select an option:
echo 1. Run Interactive Script (Recommended)
echo 2. Restore via builtin rollback system
echo 3. Restore via System Restore Point
echo 4. Exit
set /p MENUOPT=Enter your choice [1-4]:
echo 4. Update Script (Recommended after multiple runs)
echo 5. Exit
set /p MENUOPT=Enter your choice [1-5]:

set "PS_ARGS="
set "PS_TARGET=%PS_SCRIPT%"
if "%MENUOPT%"=="1" (
echo [INFO] Launching interactive script in a new PowerShell window...
start "TelemetryBlocker-Interactive" %PS_EXE% -NoProfile -ExecutionPolicy Bypass -File "%PS_SCRIPT%" -Interactive
start "TelemetryBlocker-Interactive" %PS_EXE% -NoProfile -ExecutionPolicy Bypass -File "%PS_SCRIPT%" -Interactive -EnableAuditLog
exit /b
)
if "%MENUOPT%"=="2" set "PS_ARGS=-Rollback"
if "%MENUOPT%"=="3" set "PS_ARGS=-RestorePoint"
if "%MENUOPT%"=="4" goto end
if "%MENUOPT%"=="4" (
echo [INFO] Launching script update check...
%PS_EXE% -NoProfile -ExecutionPolicy Bypass -File "%PS_SCRIPT%" -Update
echo.
pause
goto menu
)
if "%MENUOPT%"=="5" goto end

:: Only check for invalid selection for options other than 1-4
if not "%MENUOPT%"=="1" if not "%MENUOPT%"=="2" if not "%MENUOPT%"=="3" if not "%MENUOPT%"=="4" (
:: Only check for invalid selection for options other than 1-5
if not "%MENUOPT%"=="1" if not "%MENUOPT%"=="2" if not "%MENUOPT%"=="3" if not "%MENUOPT%"=="4" if not "%MENUOPT%"=="5" (
echo Invalid selection. Please try again.
echo.
goto menu
Expand Down
94 changes: 92 additions & 2 deletions windowstelementryblocker.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ===============================
# Windows Telemetry Blocker
# Script Version: nextgen-0.8 (pending review)
# Script Version: nextgen-0.9 (pending)
# ===============================


Expand All @@ -13,7 +13,9 @@ param(
[switch]$WhatIf,
[switch]$RollbackOnFailure,
[switch]$Rollback,
[switch]$RestorePoint
[switch]$RestorePoint,
[switch]$Update,
[switch]$EnableAuditLog
)

# --- Special parameter handling (outside param block) ---
Expand Down Expand Up @@ -81,6 +83,14 @@ Write-Host "===============================" -ForegroundColor Cyan
Write-Host (" Windows Telemetry Blocker v{0}" -f $ScriptVersion) -ForegroundColor Cyan
Write-Host "===============================" -ForegroundColor Cyan

# Check for updates if requested
if ($Update) {
Write-Host "Update requested. Checking for updates..." -ForegroundColor Yellow
Update-Script
Write-Host "Update check complete." -ForegroundColor Green
Write-AuditLog "Script update check performed"
}

# Fail fast for unhandled errors in scripts we call; we'll handle expected errors with try/catch
$ErrorActionPreference = 'Stop'
$VerbosePreference = 'Continue'
Expand All @@ -95,6 +105,7 @@ $errorLogFile = Join-Path $PSScriptRoot "telemetry-blocker-errors.log"
$executionStatsFile = Join-Path $PSScriptRoot "telemetry-blocker-stats.log"
$reportFile = Join-Path $PSScriptRoot "telemetry-blocker-report.md"
$modulesDir = Join-Path $PSScriptRoot "modules"
$GitHubRepo = "https://github.com/N0tHorizon/WindowsTelemetryBlocker"

# ==== Logging helpers (single authoritative definitions) ====
function Write-Log {
Expand Down Expand Up @@ -122,6 +133,66 @@ function Write-Stats {
}
}

# ==== New Feature Functions ====
function Update-Script {
Write-Host "Fetching latest version from GitHub..." -ForegroundColor Yellow
try {
# Download the main script
$mainUrl = "$GitHubRepo/raw/main/windowstelementryblocker.ps1"
$tempMain = Join-Path $PSScriptRoot "temp_main.ps1"
Invoke-WebRequest -Uri $mainUrl -OutFile $tempMain -ErrorAction Stop

# Download modules
$apiUrl = "$GitHubRepo/contents/modules"
$response = Invoke-WebRequest -Uri $apiUrl -Headers @{ "Accept" = "application/vnd.github.v3+json" } -ErrorAction Stop
$files = $response.Content | ConvertFrom-Json

foreach ($file in $files) {
if ($file.name -like "*.ps1") {
$fileUrl = $file.download_url
$tempFile = Join-Path $PSScriptRoot ("temp_{0}" -f $file.name)
Invoke-WebRequest -Uri $fileUrl -OutFile $tempFile -ErrorAction Stop
}
}

# Confirm
$confirm = Read-Host "Downloaded updates. Overwrite files? (Y/N)"
if ($confirm -eq 'Y') {
# Overwrite
Move-Item $tempMain (Join-Path $PSScriptRoot "windowstelementryblocker.ps1") -Force -ErrorAction Stop
foreach ($file in $files) {
if ($file.name -like "*.ps1") {
$tempFile = Join-Path $PSScriptRoot ("temp_{0}" -f $file.name)
$dest = Join-Path $modulesDir $file.name
Move-Item $tempFile $dest -Force -ErrorAction Stop
}
}
Write-Host "Update complete." -ForegroundColor Green
} else {
Write-Host "Update cancelled." -ForegroundColor Yellow
# Clean temp
Remove-Item (Join-Path $PSScriptRoot "temp_*") -Force -ErrorAction SilentlyContinue
}
} catch {
Write-Host ("[ERROR] Update failed: {0}" -f $_.Exception.Message) -ForegroundColor Red
# Clean temp
Remove-Item (Join-Path $PSScriptRoot "temp_*") -Force -ErrorAction SilentlyContinue
}
}

function Write-AuditLog {
param([string]$Message, [string]$EventType = "Information")
if (-not $EnableAuditLog) { return }
try {
if (-not (Get-EventLog -LogName Application -Source "TelemetryBlocker" -ErrorAction SilentlyContinue)) {
New-EventLog -LogName Application -Source "TelemetryBlocker" -ErrorAction Stop
}
Write-EventLog -LogName Application -Source "TelemetryBlocker" -EventId 1000 -EntryType $EventType -Message $Message -ErrorAction Stop
} catch {
Write-Log ("Failed to write audit log: {0}" -f $_.Exception.Message) -Error
}
}

# ==== Registry backup/export before changes ====
function Export-RegistryBackup {
try {
Expand Down Expand Up @@ -169,6 +240,7 @@ Write-Log "=== Script started ==="
Write-Log ("Windows Version: {0}" -f $winVersion)
Write-Log ("Windows Build: {0}" -f $winBuild)
Write-Log ("Script Version: {0}" -f $ScriptVersion)
Write-AuditLog ("Script started - Version {0}, Windows {1} Build {2}" -f $ScriptVersion, $winVersion, $winBuild)

# ==== Ensure modules directory exists ====
if (-not (Test-Path $modulesDir)) {
Expand All @@ -184,6 +256,14 @@ if (-not (Test-Path $modulesDir)) {
}
}

# ==== Rollback coverage scan ====
$rollbackCoverage = @{}
foreach ($mod in $moduleList) {
$rollbackPath = Join-Path $modulesDir ("{0}-rollback.ps1" -f $mod)
$rollbackCoverage[$mod] = Test-Path $rollbackPath
}
Write-Log ("Rollback coverage: {0}" -f (($rollbackCoverage.GetEnumerator() | ForEach-Object { "$($_.Key):$($_.Value)" }) -join ', '))

# ==== System helpers ====
function New-SystemRestorePoint {
try {
Expand Down Expand Up @@ -402,6 +482,8 @@ function Resolve-ModuleDependencies {
return $resolved
}



# ==== Module execution loop ====
Write-Host "`n=== Starting Module Execution ===" -ForegroundColor Cyan
$summary = @()
Expand All @@ -414,6 +496,7 @@ $toRunResolved = Resolve-ModuleDependencies -mods $toRun

foreach ($mod in $toRunResolved) {
Write-Host ("`nRunning module: {0}" -f $mod) -ForegroundColor Yellow
Write-AuditLog ("Starting module execution: {0}" -f $mod)
$moduleStart = Get-Date
try {
$modulePath = Join-Path $modulesDir ("{0}.ps1" -f $mod)
Expand All @@ -431,10 +514,12 @@ foreach ($mod in $toRunResolved) {
if ($result -eq $false) {
Write-Host ("[ERROR] Module {0} reported failure" -f $mod) -ForegroundColor Red
Write-Log ("Module {0} reported failure" -f $mod) -Error
Write-AuditLog ("Module {0} execution failed" -f $mod) "Warning"
$summary += ("Module {0} reported failure" -f $mod)
$moduleResults[$mod] = @{ Status='Failure'; Start=$moduleStart; End=(Get-Date) }
} else {
Write-Log ("Module {0} completed" -f $mod)
Write-AuditLog ("Module {0} execution completed successfully" -f $mod)
$summary += ("Module {0} completed" -f $mod)
$moduleResults[$mod] = @{ Status='Success'; Start=$moduleStart; End=(Get-Date) }
}
Expand All @@ -450,6 +535,7 @@ foreach ($mod in $toRunResolved) {
if ($RollbackOnFailure) {
Write-Host "Rolling back changes for executed modules..." -ForegroundColor Red
Write-Log ("Rollback initiated due to failure in module {0}" -f $mod)
Write-AuditLog ("Rollback initiated due to failure in module {0}" -f $mod) "Warning"

# clone and reverse executedModules safely
$executedClone = @()
Expand All @@ -463,20 +549,24 @@ foreach ($mod in $toRunResolved) {
Write-Host ("Running rollback for {0}..." -f $rmod) -ForegroundColor Yellow
. $rollbackPath
Write-Log ("Rollback for {0} completed" -f $rmod)
Write-AuditLog ("Rollback for {0} completed" -f $rmod)
$rollbackModules += $rmod
} catch {
$rbErr = if ($_.Exception) { $_.Exception.Message } else { $_.ToString() }
Write-Host ("[ERROR] Rollback failed for {0}: {1}" -f $rmod, $rbErr) -ForegroundColor Red
Write-Log ("Rollback failed for {0}: {1}" -f $rmod, $rbErr) -Error
Write-AuditLog ("Rollback failed for {0}: {1}" -f $rmod, $rbErr) "Error"
}
} else {
Write-Host ("No rollback script for {0}" -f $rmod) -ForegroundColor DarkYellow
Write-Log ("No rollback script for {0}" -f $rmod)
Write-AuditLog ("No rollback script for {0}" -f $rmod) "Warning"
}
}

Write-Host "Rollback complete. Exiting." -ForegroundColor Red
Write-Log "Rollback complete. Exiting."
Write-AuditLog "Rollback complete. Exiting."
break
} else {
$response = Read-Host "Do you want to continue with remaining modules? (Y/N)"
Expand Down
Loading