KaynaฤŸa Gรถzat

๐Ÿ“ฐ Update

VLADYSLAV BOBER 11 ay รถnce
ebeveyn
iลŸleme
a075ccf76a

+ 566 - 178
script/office_privacy_telemetry_disabler.ps1

@@ -1,23 +1,9 @@
-<#
-.SYNOPSIS
-    Office Privacy & Telemetry Disabler (PowerShell 7 edition)
-.DESCRIPTION
-    Disables logging, telemetry, CEIP, feedback, Connected Experiences,
-    scheduled telemetry tasks, updates and optionally blocks telemetry hosts
-    in the HOSTS file (with Windows-Defender exclusion).
-.NOTES
-    Author : EXLOUD
-    License: MIT
-    GitHub : https://github.com/EXLOUD
-#>
-
-[CmdletBinding(SupportsShouldProcess)]
-param (
-	[switch]$BlockHosts,
-	[switch]$Force
-)
+# Office Privacy and Telemetry Disabler
+# PowerShell script to disable Microsoft Office logging, telemetry, and privacy features
+# by EXLOUD
+# >> https://github.com/EXLOUD <<
 
-# โ”€โ”€ Color scheme โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+# Color scheme for consistent output
 $Colors = @{
 	Title    = 'Cyan'
 	Section  = 'Yellow'
@@ -25,226 +11,628 @@ $Colors = @{
 	Info	 = 'Blue'
 	Warning  = 'Yellow'
 	Error    = 'Red'
-	NotFound = 'Gray'
+	Gray	 = 'Gray'
+	Found    = 'Green'
 	Changed  = 'Magenta'
+	NotFound = 'Gray'
 }
 
-function Write-C
+# Check for admin rights at the start of the script
+Write-Host "--- Checking for admin rights ---" -ForegroundColor $Colors.Section
+
+$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
+$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
+
+if (-not $isAdmin)
 {
-	param (
-		$t,
-		$c = 'White'
-	)
-	$color = if ($Colors.ContainsKey($c)) { $Colors[$c] }
-	else { 'White' }
-	Write-Host $t -ForegroundColor $color
+	Write-Host "  โœ— Administrator privileges required." -ForegroundColor $Colors.Error
+	Write-Host "    Please run the script as Administrator to use this script." -ForegroundColor $Colors.Warning
 }
-function Write-S { param ($t) Write-C "`n--- $t ---" Section }
-function Write-O { param ($t) Write-C "  โœ“ $t" Success }
-function Write-W { param ($t) Write-C "  โš  $t" Warning }
-function Write-E { param ($t) Write-C "  โœ— $t" Error }
-function Write-N { param ($t) Write-C "  โ†’ $t" NotFound }
-function Write-X { param ($t) Write-C "  โœ“ $t" Changed }
-
-# โ”€โ”€ Admin check โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-$isAdmin = ([Security.Principal.WindowsPrincipal]`
-	[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
-	[Security.Principal.WindowsBuiltInRole]::Administrator)
-if (-not $isAdmin -and -not $Force)
+else
 {
-	Write-E "Administrator rights required. Re-run as Admin or use -Force."
-	exit 1
+	Write-Host "  โœ“ Running with administrator privileges." -ForegroundColor $Colors.Success
 }
 
-# โ”€โ”€ Office versions โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-$OfficeMap = @{
+# Office versions mapping
+$OfficeVersions = @{
 	'14.0' = 'Office 2010'
 	'15.0' = 'Office 2013'
-	'16.0' = 'Office 2016/2019/365'
+	'16.0' = 'Office 2016/2019'
 	'17.0' = 'Office 2021'
 	'18.0' = 'Office 2024'
 }
 
-$installed = $OfficeMap.Keys | Where-Object { Test-Path "HKCU:\SOFTWARE\Microsoft\Office\$_" } | Sort-Object
-if (-not $installed) { Write-E "No Office installations found."; exit }
-
-# โ”€โ”€ Registry helper (skip if key missing) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-function Set-Reg
+# Function to write colored output
+function Write-ColoredOutput
 {
-	[CmdletBinding(SupportsShouldProcess)]
 	param (
-		[string]$Path,
-		[string]$Name,
-		[string]$Type = 'DWord',
-		[object]$Value,
-		[string]$Desc = ''
+		[string]$Message,
+		[string]$Color = 'White'
 	)
-	if (-not (Test-Path $Path)) { New-Item $Path -Force | Out-Null }
-	if ($PSCmdlet.ShouldProcess("$Path\$Name", "Set $Value"))
+	
+	# Map custom colors to PowerShell colors
+	$psColor = switch ($Color)
 	{
-		Set-ItemProperty -Path $Path -Name $Name -Type $Type -Value $Value -Force
-		Write-X "$Name โ†’ $Value ($Desc)"
+		'Warning' { $Colors.Warning }
+		'Found' { $Colors.Found }
+		'Header' { $Colors.Section }
+		'Changed' { $Colors.Changed }
+		'NotFound' { $Colors.NotFound }
+		'Info' { $Colors.Info }
+		'Success' { $Colors.Success }
+		'Error' { $Colors.Error }
+		default { 'White' }
 	}
+	
+	Write-Host $Message -ForegroundColor $psColor
 }
 
-# โ”€โ”€ Registry tweaks โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-Write-S "Applying registry privacy settings"
-foreach ($ver in $installed)
-{
-	Write-C "`nProcessing $($OfficeMap[$ver])" Info
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Outlook\Options\Mail" -Name EnableLogging -Value 0 -Desc "Outlook Mail"
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Outlook\Options\Calendar" -Name EnableCalendarLogging -Value 0 -Desc "Calendar"
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Word\Options" -Name EnableLogging -Value 0 -Desc "Word"
-	Set-Reg -Path "HKCU:\SOFTWARE\Policies\Microsoft\Office\$ver\OSM" -Name EnableLogging -Value 0 -Desc "OSM"
-	Set-Reg -Path "HKCU:\SOFTWARE\Policies\Microsoft\Office\$ver\OSM" -Name EnableUpload -Value 0 -Desc "OSM Upload"
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common\ClientTelemetry" -Name DisableTelemetry -Value 1 -Desc "Telemetry"
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common\ClientTelemetry" -Name VerboseLogging -Value 0 -Desc "Verbose"
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common" -Name QMEnable -Value 0 -Desc "CEIP"
-	Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common\Feedback" -Name Enabled -Value 0 -Desc "Feedback"
-	if ($ver -ge '16.0')
+# Function to check if Office version is installed
+function Test-OfficeVersion
+{
+	param ([string]$Version)
+	
+	$registryPath = "HKCU:\SOFTWARE\Microsoft\Office\$Version"
+	return Test-Path $registryPath
+}
+
+# Function to get installed Office version
+function Get-InstalledOfficeVersion
+{
+	$installedVersions = @()
+	foreach ($version in $OfficeVersions.Keys)
 	{
-		Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common\Privacy" -Name UserContentDisabled -Value 2 -Desc "User content"
-		Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common\Privacy" -Name DownloadContentDisabled -Value 2 -Desc "Download content"
-		Set-Reg -Path "HKCU:\SOFTWARE\Microsoft\Office\$ver\Common\Internet" -Name UseOnlineContent -Value 0 -Desc "Online content"
+		if (Test-OfficeVersion $version)
+		{
+			$installedVersions += $version
+		}
 	}
+	# Sort versions in ascending order
+	return $installedVersions | Sort-Object
 }
 
-# โ”€โ”€ Scheduled-task handler (PowerShell 7) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-function Disable-Task
+# Function to set registry value with logging
+function Set-RegistryValueWithLogging
 {
+	[CmdletBinding(SupportsShouldProcess)]
 	param (
+		[string]$Path,
 		[string]$Name,
-		[string]$Description
+		[string]$Type,
+		[object]$Value,
+		[string]$Description = ""
 	)
 	
-	$task = Get-ScheduledTask -TaskName $Name -ErrorAction SilentlyContinue
-	if (-not $task)
+	if ($PSCmdlet.ShouldProcess("Registry: $Path\$Name", "Set value to $Value"))
 	{
-		Write-O "Task not found (OK): $Name"
-		return @{ Status = 'NotFound' }
+		try
+		{
+			# Check if the registry key exists
+			if (-not (Test-Path $Path))
+			{
+				Write-Host "  โ†’ Registry path not found: $Path" -ForegroundColor $Colors.NotFound
+				return
+			}
+			
+			# Create the registry key if it doesn't exist
+			if (-not (Test-Path $Path))
+			{
+				New-Item -Path $Path -Force | Out-Null
+			}
+			
+			# Set the registry value
+			Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force
+			
+			Write-Host "  โœ“ Found and changed: $Name โ†’ $Value" -ForegroundColor $Colors.Changed
+			if ($Description)
+			{
+				Write-Host "    Description: $Description" -ForegroundColor $Colors.Info
+			}
+		}
+		catch
+		{
+			Write-Host "  โœ— Error setting $Name : $($_.Exception.Message)" -ForegroundColor $Colors.Error
+		}
 	}
+}
+
+# Function to disable scheduled task with logging
+function Disable-ScheduledTaskWithLogging
+{
+	param (
+		[string]$TaskName,
+		[string]$Description = ""
+	)
 	
-	if ($task.State -eq 'Disabled')
+	try
 	{
-		Write-O "Already disabled: $Name"
-		return @{ Status = 'AlreadyDisabled' }
+		$task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
+		if ($task)
+		{
+			$taskState = $task.State
+			if ($taskState -eq 'Disabled')
+			{
+				Write-Host "  โœ“ Task already disabled: $TaskName" -ForegroundColor $Colors.Success
+			}
+			else
+			{
+				Disable-ScheduledTask -TaskName $TaskName -ErrorAction Stop | Out-Null
+				Write-Host "  โœ“ Found and disabled: $TaskName" -ForegroundColor $Colors.Changed
+			}
+			
+			if ($Description)
+			{
+				Write-Host "    Description: $Description" -ForegroundColor $Colors.Info
+			}
+		}
+		else
+		{
+			Write-Host "  โ†’ Task not found: $TaskName" -ForegroundColor $Colors.NotFound
+		}
 	}
+	catch
+	{
+		Write-Host "  โœ— Error disabling $TaskName : $($_.Exception.Message)" -ForegroundColor $Colors.Error
+	}
+}
+
+# Main script execution
+Write-Host "`n==========================================" -ForegroundColor $Colors.Title
+Write-Host "   Office Privacy and Telemetry Disabler" -ForegroundColor $Colors.Title
+Write-Host "                by EXLOUD" -ForegroundColor $Colors.Title
+Write-Host "     >> https://github.com/EXLOUD <<" -ForegroundColor $Colors.Title
+Write-Host "==========================================" -ForegroundColor $Colors.Title
+
+# Check for installed Office versions
+Write-Host "`n--- Checking for installed Office versions ---" -ForegroundColor $Colors.Section
+$installedVersions = Get-InstalledOfficeVersion
+
+if ($installedVersions.Count -eq 0)
+{
+	Write-Host "โœ— No Office installations found in registry." -ForegroundColor $Colors.Error
+	Read-Host "Press Enter to exit"
+	exit
+}
+
+Write-Host "Found Office versions:" -ForegroundColor $Colors.Found
+foreach ($version in $installedVersions)
+{
+	Write-Host "  โœ“ $($OfficeVersions[$version]) (Version $version)" -ForegroundColor $Colors.Found
+}
+
+# ----------------------------------------------------------
+# Disable Microsoft Office logging
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling Microsoft Office logging ---" -ForegroundColor $Colors.Section
+
+foreach ($version in $installedVersions)
+{
+	Write-Host "`nProcessing $($OfficeVersions[$version])..." -ForegroundColor $Colors.Info
+	
+	# Outlook logging
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Outlook\Options\Mail" -Name "EnableLogging" -Type "DWord" -Value 0 -Description "Disable Outlook mail logging"
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Outlook\Options\Calendar" -Name "EnableCalendarLogging" -Type "DWord" -Value 0 -Description "Disable Outlook calendar logging"
+	
+	# Word logging
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Word\Options" -Name "EnableLogging" -Type "DWord" -Value 0 -Description "Disable Word logging"
+	
+	# OSM (Office Service Manager)
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Policies\Microsoft\Office\$version\OSM" -Name "EnableLogging" -Type "DWord" -Value 0 -Description "Disable OSM logging"
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Policies\Microsoft\Office\$version\OSM" -Name "EnableUpload" -Type "DWord" -Value 0 -Description "Disable OSM upload"
+}
+
+# ----------------------------------------------------------
+# Disable client telemetry
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling client telemetry ---" -ForegroundColor $Colors.Section
+
+# Common telemetry settings
+Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\Common\ClientTelemetry" -Name "DisableTelemetry" -Type "DWord" -Value 1 -Description "Disable common telemetry"
+Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\Common\ClientTelemetry" -Name "VerboseLogging" -Type "DWord" -Value 0 -Description "Disable verbose logging"
+
+foreach ($version in $installedVersions)
+{
+	Write-Host "`nProcessing $($OfficeVersions[$version]) telemetry..." -ForegroundColor $Colors.Info
+	
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\ClientTelemetry" -Name "DisableTelemetry" -Type "DWord" -Value 1 -Description "Disable telemetry"
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\ClientTelemetry" -Name "VerboseLogging" -Type "DWord" -Value 0 -Description "Disable verbose logging"
+}
+
+# ----------------------------------------------------------
+# Disable Customer Experience Improvement Program
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling Customer Experience Improvement Program ---" -ForegroundColor $Colors.Section
+
+# Common CEIP settings
+Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\Common" -Name "QMEnable" -Type "DWord" -Value 0 -Description "Disable common CEIP"
+
+foreach ($version in $installedVersions)
+{
+	Write-Host "`nProcessing $($OfficeVersions[$version]) CEIP..." -ForegroundColor $Colors.Info
+	
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common" -Name "QMEnable" -Type "DWord" -Value 0 -Description "Disable CEIP"
+}
+
+# ----------------------------------------------------------
+# Disable feedback
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling feedback ---" -ForegroundColor $Colors.Section
+
+# Common feedback settings
+Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\Common\Feedback" -Name "Enabled" -Type "DWord" -Value 0 -Description "Disable common feedback"
+
+foreach ($version in $installedVersions)
+{
+	Write-Host "`nProcessing $($OfficeVersions[$version]) feedback..." -ForegroundColor $Colors.Info
+	
+	Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\Feedback" -Name "Enabled" -Type "DWord" -Value 0 -Description "Disable feedback"
+}
+
+# ----------------------------------------------------------
+# Disable Connected Experiences (Office 2016 and later)
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling Connected Experiences ---" -ForegroundColor $Colors.Section
+
+$modernVersions = $installedVersions | Where-Object { $_ -in @('16.0', '17.0', '18.0') }
+
+if ($modernVersions.Count -gt 0)
+{
+	foreach ($version in $modernVersions)
+	{
+		Write-Host "`nProcessing $($OfficeVersions[$version]) Connected Experiences..." -ForegroundColor $Colors.Info
+		
+		Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\Privacy" -Name "UserContentDisabled" -Type "DWord" -Value 2 -Description "Disable user content experiences"
+		Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\Privacy" -Name "DownloadContentDisabled" -Type "DWord" -Value 2 -Description "Disable download content experiences"
+		Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\Internet" -Name "UseOnlineContent" -Type "DWord" -Value 0 -Description "Disable online content"
+	}
+}
+else
+{
+	Write-Host "โ†’ No modern Office versions found for Connected Experiences settings." -ForegroundColor $Colors.NotFound
+}
+
+# ----------------------------------------------------------
+# Disable telemetry agent scheduled tasks
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling telemetry agent scheduled tasks ---" -ForegroundColor $Colors.Section
+
+$telemetryTasks = @(
+	@{ Name = "Microsoft\Office\OfficeTelemetryAgentFallBack"; Description = "Office 2013 Telemetry Agent Fallback" },
+	@{ Name = "Microsoft\Office\OfficeTelemetryAgentLogOn"; Description = "Office 2013 Telemetry Agent Logon" },
+	@{ Name = "Microsoft\Office\OfficeTelemetryAgentFallBack2016"; Description = "Office 2016/2019 Telemetry Agent Fallback" },
+	@{ Name = "Microsoft\Office\OfficeTelemetryAgentLogOn2016"; Description = "Office 2016/2019 Telemetry Agent Logon" },
+	@{ Name = "Microsoft\Office\OfficeBackgroundTaskHandlerRegistration"; Description = "Office Background Task Handler Registration" },
+	@{ Name = "Microsoft\Office\OfficeBackgroundTaskHandlerLogon"; Description = "Office Background Task Handler Logon" },
+	@{ Name = "Microsoft\Office\Office Automatic Updates"; Description = "Office Automatic Updates" },
+	@{ Name = "Microsoft\Office\Office Automatic Updates 2.0"; Description = "Office Automatic Updates 2.0" },
+	@{ Name = "Microsoft\Office\Office Feature Updates"; Description = "Office Feature Updates" },
+	@{ Name = "Microsoft\Office\Office Feature Updates Logon"; Description = "Office Feature Updates Logon" }
+)
+
+Write-Host "`nProcessing telemetry agent scheduled tasks..." -ForegroundColor $Colors.Info
+$telemetryTasksProcessed = 0
+$telemetryTasksDisabled = 0
+$telemetryTasksNotFound = 0
+
+foreach ($task in $telemetryTasks)
+{
+	$telemetryTasksProcessed++
 	
 	try
 	{
-		Disable-ScheduledTask -TaskName $Name -ErrorAction Stop | Out-Null
-		Write-X "Disabled: $Name ($Description)"
-		return @{ Status = 'Disabled' }
+		$scheduledTask = Get-ScheduledTask -TaskName $task.Name -ErrorAction SilentlyContinue
+		if ($scheduledTask)
+		{
+			$taskState = $scheduledTask.State
+			if ($taskState -eq 'Disabled')
+			{
+				Write-Host "  โœ“ Task already disabled: $($task.Name)" -ForegroundColor $Colors.Changed
+			}
+			else
+			{
+				Disable-ScheduledTask -TaskName $task.Name -ErrorAction Stop | Out-Null
+				Write-Host "  โœ“ Found and disabled: $($task.Name)" -ForegroundColor $Colors.Changed
+				$telemetryTasksDisabled++
+			}
+			
+			Write-Host "    Description: $($task.Description)" -ForegroundColor $Colors.Info
+		}
+		else
+		{
+			Write-Host "  โ†’ Task not found: $($task.Name)" -ForegroundColor $Colors.Changed
+			$telemetryTasksNotFound++
+		}
 	}
 	catch
 	{
-		Write-E "Failed to disable $Name : $($_.Exception.Message)"
-		return @{ Status = 'Error' }
+		Write-Host "  โœ— Error disabling $($task.Name) : $($_.Exception.Message)" -ForegroundColor $Colors.Error
 	}
 }
 
-# โ”€โ”€ Task list (same as before) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-$tasks = @(
-	@{ Name = 'Microsoft\Office\OfficeTelemetryAgentFallBack'; Desc = 'Telemetry Agent 2013' },
-	@{ Name = 'Microsoft\Office\OfficeTelemetryAgentLogOn'; Desc = 'Telemetry Logon 2013' },
-	@{ Name = 'Microsoft\Office\OfficeTelemetryAgentFallBack2016'; Desc = 'Telemetry Agent 2016+' },
-	@{ Name = 'Microsoft\Office\OfficeTelemetryAgentLogOn2016'; Desc = 'Telemetry Logon 2016+' },
-	@{ Name = 'Microsoft\Office\OfficeBackgroundTaskHandlerRegistration'; Desc = 'Background registration' },
-	@{ Name = 'Microsoft\Office\OfficeBackgroundTaskHandlerLogon'; Desc = 'Background logon' },
-	@{ Name = 'Microsoft\Office\Office Automatic Updates'; Desc = 'Auto-updates' },
-	@{ Name = 'Microsoft\Office\Office Automatic Updates 2.0'; Desc = 'Auto-updates 2.0' },
-	@{ Name = 'Microsoft\Office\Office Feature Updates'; Desc = 'Feature updates' },
-	@{ Name = 'Microsoft\Office\Office Feature Updates Logon'; Desc = 'Feature updates logon' },
-	@{ Name = 'Microsoft\Office\Office 15 Subscription Heartbeat'; Desc = 'Subscription heartbeat 2013' },
-	@{ Name = 'Microsoft\Office\Office 16 Subscription Heartbeat'; Desc = 'Subscription heartbeat 2016+' },
-	@{ Name = 'Microsoft\Office\Office Subscription Maintenance'; Desc = 'Subscription maintenance' },
-	@{ Name = 'Microsoft\Office\Office ClickToRun Service Monitor'; Desc = 'Click-to-Run monitor' }
+Write-Host "`nTelemetry tasks summary:" -ForegroundColor $Colors.Info
+Write-Host "  Total processed: $telemetryTasksProcessed" -ForegroundColor $Colors.Info
+Write-Host "  Tasks disabled: $telemetryTasksDisabled" -ForegroundColor $Colors.Changed
+Write-Host "  Tasks not found: $telemetryTasksNotFound" -ForegroundColor $Colors.NotFound
+
+# ----------------------------------------------------------
+# Disable Subscription Heartbeat
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling Subscription Heartbeat ---" -ForegroundColor $Colors.Section
+
+$heartbeatTasks = @(
+	@{ Name = "Microsoft\Office\Office 15 Subscription Heartbeat"; Description = "Office 2013 Subscription Heartbeat" },
+	@{ Name = "Microsoft\Office\Office 16 Subscription Heartbeat"; Description = "Office 2016/2019 Subscription Heartbeat" },
+	@{ Name = "Microsoft\Office\Office Subscription Maintenance"; Description = "Office Subscription Maintenance" },
+	@{ Name = "Microsoft\Office\Office ClickToRun Service Monitor"; Description = "Office ClickToRun Service Monitor" }
 )
 
-# โ”€โ”€ Processing with counters โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-$stats = @{
-	Total		    = $tasks.Count
-	Disabled	    = 0
-	AlreadyDisabled = 0
-	NotFound	    = 0
-	Errors		    = 0
+Write-Host "`nProcessing subscription heartbeat tasks..." -ForegroundColor $Colors.Info
+$heartbeatTasksProcessed = 0
+$heartbeatTasksDisabled = 0
+$heartbeatTasksNotFound = 0
+
+foreach ($task in $heartbeatTasks)
+{
+	$heartbeatTasksProcessed++
+	
+	try
+	{
+		$scheduledTask = Get-ScheduledTask -TaskName $task.Name -ErrorAction SilentlyContinue
+		if ($scheduledTask)
+		{
+			$taskState = $scheduledTask.State
+			if ($taskState -eq 'Disabled')
+			{
+				Write-Host "  โœ“ Task already disabled: $($task.Name)" -ForegroundColor $Colors.Changed
+			}
+			else
+			{
+				Disable-ScheduledTask -TaskName $task.Name -ErrorAction Stop | Out-Null
+				Write-Host "  โœ“ Found and disabled: $($task.Name)" -ForegroundColor $Colors.Changed
+				$heartbeatTasksDisabled++
+			}
+			
+			Write-Host "    Description: $($task.Description)" -ForegroundColor $Colors.Info
+		}
+		else
+		{
+			Write-Host "  โ†’ Task not found: $($task.Name)" -ForegroundColor $Colors.Changed
+			$heartbeatTasksNotFound++
+		}
+	}
+	catch
+	{
+		Write-Host "  โœ— Error disabling $($task.Name) : $($_.Exception.Message)" -ForegroundColor $Colors.Error
+	}
 }
 
-Write-S "Disabling telemetry scheduled tasks"
-foreach ($t in $tasks)
+Write-Host "`nHeartbeat tasks summary:" -ForegroundColor $Colors.Info
+Write-Host "  Total processed: $heartbeatTasksProcessed" -ForegroundColor $Colors.Info
+Write-Host "  Tasks disabled: $heartbeatTasksDisabled" -ForegroundColor $Colors.Changed
+Write-Host "  Tasks not found: $heartbeatTasksNotFound" -ForegroundColor $Colors.NotFound
+
+# ----------------------------------------------------------
+# Disable Office updates and notifications
+# ----------------------------------------------------------
+Write-Host "`n--- Disabling Office updates and notifications ---" -ForegroundColor $Colors.Section
+
+$updateVersions = $installedVersions | Where-Object { $_ -in @('16.0', '17.0', '18.0') }
+
+if ($updateVersions.Count -gt 0)
 {
-	$result = Disable-Task -Name $t.Name -Description $t.Desc
-	switch ($result.Status)
+	foreach ($version in $updateVersions)
 	{
-		'Disabled'        { $stats.Disabled++ }
-		'AlreadyDisabled' { $stats.AlreadyDisabled++ }
-		'NotFound'        { $stats.NotFound++ }
-		'Error'           { $stats.Errors++ }
+		Write-Host "`nProcessing $($OfficeVersions[$version]) updates..." -ForegroundColor $Colors.Info
+		
+		Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\OfficeUpdate" -Name "OfficeMgmtCOM" -Type "DWord" -Value 0 -Description "Disable Office management COM"
+		Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\OfficeUpdate" -Name "EnableAutomaticUpdates" -Type "DWord" -Value 0 -Description "Disable automatic updates"
+		Set-RegistryValueWithLogging -Path "HKCU:\SOFTWARE\Microsoft\Office\$version\Common\PTWatson" -Name "PTWOptIn" -Type "DWord" -Value 0 -Description "Disable Watson error reporting"
 	}
 }
+else
+{
+	Write-Host "โ†’ No modern Office versions found for update settings." -ForegroundColor $Colors.NotFound
+}
 
-Write-C ("Tasks processed: {0} | Disabled: {1} | Already-off: {2} | Not-found (OK): {3} | Errors: {4}" `
-	-f $stats.Total, $stats.Disabled, $stats.AlreadyDisabled, $stats.NotFound, $stats.Errors) Info
+# ----------------------------------------------------------
+# Summary
+# ----------------------------------------------------------
+Write-Host "`n==========================================" -ForegroundColor $Colors.Title
+Write-Host "                  Summary" -ForegroundColor $Colors.Title
+Write-Host "==========================================" -ForegroundColor $Colors.Title
 
-# โ”€โ”€ HOSTS file block (with Defender exclusion) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-if ($BlockHosts -or ($PSCmdlet.ShouldContinue(
-			'Block Microsoft telemetry hosts via hosts file?',
-			'Hosts file protection')))
+Write-Host "`nOffice privacy and telemetry settings have been applied to:" -ForegroundColor $Colors.Info
+foreach ($version in $installedVersions)
 {
-	$hostsPath = "$env:SystemRoot\System32\drivers\etc\hosts"
-	
-	# Defender exclusion
+	Write-Host "  โœ“ $($OfficeVersions[$version])" -ForegroundColor $Colors.Found
+}
+
+Write-Host "`nScheduled tasks processed:" -ForegroundColor $Colors.Info
+$telemetryTasksStatus = if ($telemetryTasksErrors -gt 0) { $Colors.Error }
+else { $Colors.Success }
+$heartbeatTasksStatus = if ($heartbeatTasksErrors -gt 0) { $Colors.Error }
+else { $Colors.Success }
+Write-Host "  โ€ข Telemetry tasks: $telemetryTasksProcessed (disabled: $telemetryTasksDisabled, not found: $telemetryTasksNotFound$(if ($telemetryTasksErrors -gt 0) { ", errors: $telemetryTasksErrors" }))" -ForegroundColor $telemetryTasksStatus
+Write-Host "  โ€ข Heartbeat tasks: $heartbeatTasksProcessed (disabled: $heartbeatTasksDisabled, not found: $heartbeatTasksNotFound$(if ($heartbeatTasksErrors -gt 0) { ", errors: $heartbeatTasksErrors" }))" -ForegroundColor $heartbeatTasksStatus
+
+Write-Host "`nLegend:" -ForegroundColor White
+Write-Host "โœ“ " -NoNewline -ForegroundColor $Colors.Success; Write-Host "Action completed successfully"
+Write-Host "โœ“ " -NoNewline -ForegroundColor $Colors.Changed; Write-Host "Setting changed"
+Write-Host "โ†’ " -NoNewline -ForegroundColor $Colors.Info; Write-Host "Information or preparatory action"
+Write-Host "โ†’ " -NoNewline -ForegroundColor $Colors.NotFound; Write-Host "Component not found, skipped"
+Write-Host "โœ— " -NoNewline -ForegroundColor $Colors.Error; Write-Host "Error occurred"
+
+Write-Host "`nNote: Some changes may require restarting Office applications to take effect." -ForegroundColor $Colors.Warning
+
+# ----------------------------------------------------------
+# Additional option: Block Microsoft Office telemetry hosts
+# ----------------------------------------------------------
+Write-Host "`n--- Additional Option: Block Telemetry Hosts ---" -ForegroundColor $Colors.Section
+$blockHosts = Read-Host "Do you want to block Microsoft Office telemetry hosts in the hosts file? (y/n)"
+if ($blockHosts -eq 'y' -or $blockHosts -eq 'Y' -or $blockHosts -eq 'yes' -or $blockHosts -eq 'Yes')
+{
+	Write-Host "`nBlocking Microsoft Office telemetry hosts..." -ForegroundColor $Colors.Info
 	try
 	{
-		Add-MpPreference -ExclusionPath $hostsPath -EA Stop
-		Write-O "Hosts file added to Windows Defender exclusions"
+		Add-MpPreference -ExclusionPath "$env:SystemRoot\System32\drivers\etc\hosts"
+		Write-Host "  โœ“ Hosts file added to Windows Defender exclusions" -ForegroundColor $Colors.Success
 	}
-	catch { Write-W "Could not add Defender exclusion (not critical)" }
-	
-	$domains = @(
-		"vortex.data.microsoft.com", "vortex-win.data.microsoft.com",
-		"telecommand.telemetry.microsoft.com", "telecommand.telemetry.microsoft.com.nsatc.net",
-		"oca.telemetry.microsoft.com", "oca.telemetry.microsoft.com.nsatc.net",
-		"sqm.telemetry.microsoft.com", "sqm.telemetry.microsoft.com.nsatc.net",
-		"watson.telemetry.microsoft.com", "watson.telemetry.microsoft.com.nsatc.net",
-		"redir.metaservices.microsoft.com", "choice.microsoft.com", "choice.microsoft.com.nsatc.net",
-		"df.telemetry.microsoft.com", "reports.wes.df.telemetry.microsoft.com",
-		"wes.df.telemetry.microsoft.com", "services.wes.df.telemetry.microsoft.com",
-		"sqm.df.telemetry.microsoft.com", "telemetry.microsoft.com",
-		"watson.ppe.telemetry.microsoft.com", "telemetry.appex.bing.net", "telemetry.urs.microsoft.com",
-		"settings-sandbox.data.microsoft.com", "vortex-sandbox.data.microsoft.com",
-		"survey.watson.microsoft.com", "watson.live.com", "watson.microsoft.com",
-		"statsfe2.ws.microsoft.com", "corpext.msitadfs.glbdns2.microsoft.com",
-		"compatexchange.cloudapp.net", "cs1.wpc.v0cdn.net", "a-0001.a-msedge.net",
-		"statsfe2.update.microsoft.com.akadns.net", "sls.update.microsoft.com.akadns.net",
-		"fe2.update.microsoft.com.akadns.net", "diagnostics.support.microsoft.com",
-		"corp.sts.microsoft.com", "statsfe1.ws.microsoft.com", "pre.footprintpredict.com",
-		"i1.services.social.microsoft.com", "i1.services.social.microsoft.com.nsatc.net",
-		"feedback.windows.com", "feedback.microsoft-hohm.com", "feedback.search.microsoft.com"
+	catch
+	{
+		Write-Host "  โš  Could not add hosts file to Defender exclusions (not critical)" -ForegroundColor $Colors.Warning
+	}
+	$hostsToBlock = @(
+		"vortex.data.microsoft.com",
+		"vortex-win.data.microsoft.com",
+		"telecommand.telemetry.microsoft.com",
+		"telecommand.telemetry.microsoft.com.nsatc.net",
+		"oca.telemetry.microsoft.com",
+		"oca.telemetry.microsoft.com.nsatc.net",
+		"sqm.telemetry.microsoft.com",
+		"sqm.telemetry.microsoft.com.nsatc.net",
+		"watson.telemetry.microsoft.com",
+		"watson.telemetry.microsoft.com.nsatc.net",
+		"redir.metaservices.microsoft.com",
+		"choice.microsoft.com",
+		"choice.microsoft.com.nsatc.net",
+		"df.telemetry.microsoft.com",
+		"reports.wes.df.telemetry.microsoft.com",
+		"wes.df.telemetry.microsoft.com",
+		"services.wes.df.telemetry.microsoft.com",
+		"sqm.df.telemetry.microsoft.com",
+		"telemetry.microsoft.com",
+		"watson.ppe.telemetry.microsoft.com",
+		"telemetry.appex.bing.net",
+		"telemetry.urs.microsoft.com",
+		"telemetry.appex.bing.net",
+		"settings-sandbox.data.microsoft.com",
+		"vortex-sandbox.data.microsoft.com",
+		"survey.watson.microsoft.com",
+		"watson.live.com",
+		"watson.microsoft.com",
+		"statsfe2.ws.microsoft.com",
+		"corpext.msitadfs.glbdns2.microsoft.com",
+		"compatexchange.cloudapp.net",
+		"cs1.wpc.v0cdn.net",
+		"a-0001.a-msedge.net",
+		"statsfe2.update.microsoft.com.akadns.net",
+		"sls.update.microsoft.com.akadns.net",
+		"fe2.update.microsoft.com.akadns.net",
+		"diagnostics.support.microsoft.com",
+		"corp.sts.microsoft.com",
+		"statsfe1.ws.microsoft.com",
+		"pre.footprintpredict.com",
+		"i1.services.social.microsoft.com",
+		"i1.services.social.microsoft.com.nsatc.net",
+		"feedback.windows.com",
+		"feedback.microsoft-hohm.com",
+		"feedback.search.microsoft.com"
 	)
+	$hostsFilePath = "$env:SystemRoot\System32\drivers\etc\hosts"
 	
-	$backup = "$hostsPath.backup.$(Get-Date -Format 'yyyyMMddHHmmss')"
-	Copy-Item $hostsPath $backup
-	Write-O "Hosts backed up to $backup"
-	
-	$hosts = Get-Content $hostsPath -Raw
-	$new = $domains | Where-Object { $hosts -notmatch [regex]::Escape($_) } |
-	ForEach-Object { "0.0.0.0 $_" }
-	
-	if ($new)
+	try
 	{
-		$new = @("`n# Office-Telemetry Block - $(Get-Date)") + $new + "# End of block`n"
-		Add-Content $hostsPath $new
-		Write-X "Added $($new.Count - 2) blocked domains"
+		$hostsFileInfo = Get-Item $hostsFilePath -ErrorAction Stop
+		$originalAttributes = $hostsFileInfo.Attributes
+		$wasReadOnly = $hostsFileInfo.IsReadOnly
+		if ($wasReadOnly)
+		{
+			Write-Host "  โ„น Hosts file is read-only, temporarily removing read-only attribute..." -ForegroundColor $Colors.Warning
+			Set-ItemProperty -Path $hostsFilePath -Name IsReadOnly -Value $false
+		}
+		$currentHosts = Get-Content $hostsFilePath -ErrorAction Stop
+		$backupPath = "$hostsFilePath.backup.$(Get-Date -Format 'yyyyMMdd_HHmmss')"
+		Copy-Item $hostsFilePath $backupPath
+		Write-Host "  โœ“ Hosts file backed up to: $backupPath" -ForegroundColor $Colors.Success
+		$hostsAdded = 0
+		$hostsSkipped = 0
+		$newEntries = @()
+		foreach ($hostname in $hostsToBlock)
+		{
+			$hostEntry = "0.0.0.0 $hostname"
+			if ($currentHosts -notcontains $hostEntry -and
+				$currentHosts -notmatch "127\.0\.0\.1\s+$([regex]::Escape($hostname))" -and
+				$currentHosts -notmatch "0\.0\.0\.0\s+$([regex]::Escape($hostname))")
+			{
+				$newEntries += $hostEntry
+				$hostsAdded++
+				Write-Host "  โœ“ Will block: $hostname" -ForegroundColor $Colors.Changed
+			}
+			else
+			{
+				$hostsSkipped++
+				Write-Host "  โ†’ Already blocked: $hostname" -ForegroundColor $Colors.Success
+			}
+		}
+		if ($newEntries.Count -gt 0)
+		{
+			$newEntries = @("`n# Microsoft Office Telemetry Hosts - Blocked by Office Privacy Disabler") + $newEntries + @("# End of Office Telemetry Hosts`n")
+			Add-Content $hostsFilePath $newEntries
+			Write-Host "`n  โœ“ Added $hostsAdded new entries to hosts file" -ForegroundColor $Colors.Success
+		}
+		if ($wasReadOnly)
+		{
+			Set-ItemProperty -Path $hostsFilePath -Name IsReadOnly -Value $true
+			Write-Host "  โœ“ Restored read-only attribute to hosts file" -ForegroundColor $Colors.Success
+		}
+		Write-Host "`n  Hosts blocking summary:" -ForegroundColor $Colors.Info
+		Write-Host "    Total hosts: $($hostsToBlock.Count)" -ForegroundColor $Colors.Info
+		Write-Host "    Newly blocked: $hostsAdded" -ForegroundColor $Colors.Changed
+		Write-Host "    Already blocked: $hostsSkipped" -ForegroundColor $Colors.Success
+		try
+		{
+			$flushSuccess = $false
+			# Method 1: ipconfig
+			try
+			{
+				& "$env:SystemRoot\System32\ipconfig.exe" /flushdns | Out-Null
+				$flushSuccess = $true
+			}
+			catch
+			{
+				# Method 2: Clear-DnsClientCache (Windows 8+)
+				try
+				{
+					Clear-DnsClientCache -ErrorAction Stop
+					$flushSuccess = $true
+				}
+				catch { }
+			}
+			if ($flushSuccess)
+			{
+				Write-Host "  โœ“ DNS cache flushed" -ForegroundColor $Colors.Success
+			}
+			else
+			{
+				Write-Host "  โš  Could not flush DNS cache (not critical)" -ForegroundColor $Colors.Warning
+			}
+		}
+		catch
+		{
+			Write-Host "  โš  Could not flush DNS cache (not critical)" -ForegroundColor $Colors.Warning
+		}
 	}
-	else { Write-N "All domains already blocked" }
-	
-	Clear-DnsClientCache -EA SilentlyContinue
-	Write-O "DNS cache flushed"
+	catch
+	{
+		Write-Host "  โœ— Error modifying hosts file: $($_.Exception.Message)" -ForegroundColor $Colors.Error
+		if ($wasReadOnly -and (Test-Path $hostsFilePath))
+		{
+			try
+			{
+				Set-ItemProperty -Path $hostsFilePath -Name IsReadOnly -Value $true
+				Write-Host "  โœ“ Restored read-only attribute after error" -ForegroundColor $Colors.Warning
+			}
+			catch
+			{
+				Write-Host "  โœ— Could not restore read-only attribute: $($_.Exception.Message)" -ForegroundColor $Colors.Error
+			}
+		}
+	}
+}
+else
+{
+	Write-Host "Hosts blocking skipped." -ForegroundColor $Colors.Info
 }
 
-# โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-Write-S "Summary"
-$installed | ForEach-Object { Write-C "  โœ“ $($OfficeMap[$_])" Found }
-Write-C "`nRestart Office applications for changes to take effect." Warning
-Write-C "`nScript completed successfully!" Success
+Write-Host "`nScript completed successfully!" -ForegroundColor $Colors.Success
+Read-Host "Press Enter to exit"