off_telemetry_ps5_win7+.ps1 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. <#
  2. .SYNOPSIS
  3. Improved comprehensive script to disable telemetry in Microsoft development tools
  4. .DESCRIPTION
  5. ====================================================================================
  6. Based on off_telemetry_ps5.ps1 but without "emojis" for OS win7-8.1 (works on win10/11)
  7. P.S. Replace to text : [INFO], [SKIP]..
  8. ====================================================================================
  9. This script safely disables telemetry, crash reporting, and data collection for:
  10. - Visual Studio 2015-2022 (only if installed)
  11. - Visual Studio Code (only if installed)
  12. - .NET CLI
  13. - NuGet
  14. - Various Visual Studio services
  15. - PowerShell 7.x (Windows 8+ only)
  16. - Visual Studio Background Download (automatic component downloads)
  17. .NOTES
  18. Must be run as Administrator
  19. Improved safety - only modifies existing registry paths
  20. Compatible with PowerShell 5.x
  21. Includes comprehensive backup and restore functionality
  22. .PARAMETER CreateBackup
  23. Creates registry backup before making changes
  24. .PARAMETER RestoreBackup
  25. Restores registry from backup file
  26. .PARAMETER BackupPath
  27. Path for backup file (default: Desktop)
  28. .EXAMPLE
  29. .\off_telemetry_ps5_win7+.ps1 -CreateBackup
  30. .\off_telemetry_ps5_win7+.ps1 -RestoreBackup -BackupPath "C:\Backup\registry_backup.reg"
  31. #>
  32. param(
  33. [switch]$CreateBackup,
  34. [switch]$RestoreBackup,
  35. [string]$BackupPath = "$env:USERPROFILE\Desktop\telemetry_backup_$(Get-Date -Format 'yyyyMMdd_HHmmss').reg",
  36. [switch]$DisableBackgroundDownload
  37. )
  38. $serviceProcessed = $false
  39. # Color scheme for consistent output
  40. $Colors = @{
  41. Title = 'Cyan'
  42. Section = 'Yellow'
  43. Success = 'Green'
  44. Info = 'Blue'
  45. Warning = 'Yellow'
  46. Error = 'Red'
  47. Gray = 'Gray'
  48. }
  49. Write-Host "======================================================" -ForegroundColor $Colors.Title
  50. Write-Host " by EXLOUD" -ForegroundColor $Colors.Title
  51. Write-Host "======================================================" -ForegroundColor $Colors.Title
  52. # =======================================================
  53. # BACKUP AND RESTORE FUNCTIONS
  54. # =======================================================
  55. function New-RegistryBackup {
  56. param([string]$BackupFile)
  57. Write-Host "`n--- Creating Registry Backup ---" -ForegroundColor $Colors.Section
  58. try {
  59. $backupKeys = @(
  60. "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VSCommon",
  61. "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VSCommon",
  62. "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\VisualStudio",
  63. "HKEY_CURRENT_USER\Software\Microsoft\VisualStudio",
  64. "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\Setup",
  65. "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\Setup"
  66. )
  67. $backupResult = $true
  68. foreach ($key in $backupKeys) {
  69. $regFile = $BackupFile -replace '\.reg$', "_$($key -replace '[\\:]', '_').reg"
  70. $null = & reg export $key $regFile /y 2>$null
  71. if ($LASTEXITCODE -eq 0) {
  72. Write-Host "[OK] Backed up: $key" -ForegroundColor $Colors.Success
  73. } else {
  74. Write-Host "[INFO] Key not found (skipped): $key" -ForegroundColor $Colors.Gray
  75. }
  76. }
  77. Write-Host "[OK] Registry backup completed" -ForegroundColor $Colors.Success
  78. return $backupResult
  79. }
  80. catch {
  81. Write-Host "[ERROR] Failed to create backup: $_" -ForegroundColor $Colors.Error
  82. return $false
  83. }
  84. }
  85. function Restore-RegistryBackup {
  86. param([string]$BackupFile)
  87. Write-Host "`n--- Restoring Registry Backup ---" -ForegroundColor $Colors.Section
  88. if (!(Test-Path $BackupFile)) {
  89. Write-Host "[ERROR] Backup file not found: $BackupFile" -ForegroundColor $Colors.Error
  90. return $false
  91. }
  92. try {
  93. $null = & reg import $BackupFile
  94. if ($LASTEXITCODE -eq 0) {
  95. Write-Host "[OK] Registry restored from: $BackupFile" -ForegroundColor $Colors.Success
  96. return $true
  97. } else {
  98. Write-Host "[ERROR] Failed to restore registry" -ForegroundColor $Colors.Error
  99. return $false
  100. }
  101. }
  102. catch {
  103. Write-Host "[ERROR] Error restoring backup: $_" -ForegroundColor $Colors.Error
  104. return $false
  105. }
  106. }
  107. # =======================================================
  108. # SAFE REGISTRY FUNCTIONS
  109. # =======================================================
  110. function Set-SafeRegistryValue {
  111. param(
  112. [string]$Path,
  113. [string]$Name,
  114. [object]$Value,
  115. [string]$Type = 'DWORD',
  116. [switch]$CreatePath
  117. )
  118. try {
  119. # Check if path exists
  120. if (!(Test-Path $Path)) {
  121. if ($CreatePath) {
  122. $null = New-Item -Path $Path -Force
  123. Write-Host "[INFO] Created registry path: $Path" -ForegroundColor $Colors.Info
  124. } else {
  125. Write-Host "[SKIP] Registry path not found, skipping: $Path" -ForegroundColor $Colors.Gray
  126. return $false
  127. }
  128. } else {
  129. Write-Host "[INFO] Found registry path: $Path" -ForegroundColor $Colors.Info
  130. }
  131. # Check current value
  132. $currentValue = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue
  133. if ($currentValue -and $currentValue.$Name -eq $Value) {
  134. Write-Host "[OK] $Name already set to $Value" -ForegroundColor $Colors.Success
  135. return $true
  136. }
  137. # Set new value
  138. $null = New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType $Type -Force -ErrorAction Stop
  139. Write-Host "[OK] Set $Name to $Value in $Path" -ForegroundColor $Colors.Success
  140. return $true
  141. }
  142. catch {
  143. Write-Host "[ERROR] Failed to set $Name in $Path : $_" -ForegroundColor $Colors.Error
  144. return $false
  145. }
  146. }
  147. function Remove-TelemetryDirectory {
  148. param([string]$Path)
  149. if (Test-Path $Path) {
  150. try {
  151. $itemCount = (Get-ChildItem -Path $Path -Recurse -ErrorAction SilentlyContinue | Measure-Object).Count
  152. if ($itemCount -gt 0) {
  153. Remove-Item -Path $Path -Recurse -Force -ErrorAction Stop
  154. Write-Host "[OK] Removed telemetry directory: $Path ($itemCount items)" -ForegroundColor $Colors.Success
  155. } else {
  156. Write-Host "[INFO] Telemetry directory already empty: $Path" -ForegroundColor $Colors.Info
  157. }
  158. }
  159. catch {
  160. Write-Host "[ERROR] Failed to remove: $Path - $_" -ForegroundColor $Colors.Error
  161. }
  162. } else {
  163. Write-Host "[SKIP] Telemetry directory not found: $Path" -ForegroundColor $Colors.Gray
  164. }
  165. }
  166. function Disable-BackgroundDownloadTasks {
  167. Write-Host "[INFO] Checking for Visual Studio BackgroundDownload scheduled tasks..." -ForegroundColor $Colors.Info
  168. try {
  169. $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object {
  170. $_.TaskName -like "*BackgroundDownload*" -or
  171. ($_.TaskPath -like "*VisualStudio*" -and $_.TaskName -like "*BackgroundDownload*")
  172. }
  173. if ($tasks) {
  174. foreach ($task in $tasks) {
  175. Write-Host "[INFO] Found task: $($task.TaskName) at $($task.TaskPath)" -ForegroundColor $Colors.Info
  176. if ($task.State -eq "Ready") {
  177. try {
  178. Disable-ScheduledTask -TaskName $task.TaskName -TaskPath $task.TaskPath -Confirm:$false -ErrorAction Stop
  179. Write-Host "[OK] Disabled task: $($task.TaskName)" -ForegroundColor $Colors.Success
  180. }
  181. catch {
  182. Write-Host "[ERROR] Could not disable task $($task.TaskName): $_" -ForegroundColor $Colors.Error
  183. }
  184. } else {
  185. Write-Host "[OK] Task already disabled: $($task.TaskName)" -ForegroundColor $Colors.Success
  186. }
  187. }
  188. return $true
  189. } else {
  190. Write-Host "[SKIP] No Visual Studio BackgroundDownload tasks found" -ForegroundColor $Colors.Gray
  191. return $false
  192. }
  193. } catch {
  194. Write-Host "[ERROR] Error checking scheduled tasks: $_" -ForegroundColor $Colors.Error
  195. return $false
  196. }
  197. }
  198. function Stop-BackgroundDownloadProcesses {
  199. Write-Host "[INFO] Checking for running BackgroundDownload processes..." -ForegroundColor $Colors.Info
  200. try {
  201. $processes = Get-Process -Name "BackgroundDownload" -ErrorAction SilentlyContinue
  202. if ($processes) {
  203. foreach ($process in $processes) {
  204. try {
  205. Stop-Process -Id $process.Id -Force -ErrorAction Stop
  206. Write-Host "[OK] Stopped process: BackgroundDownload.exe (PID: $($process.Id))" -ForegroundColor $Colors.Success
  207. }
  208. catch {
  209. Write-Host "[ERROR] Could not stop process PID $($process.Id): $_" -ForegroundColor $Colors.Error
  210. }
  211. }
  212. return $true
  213. } else {
  214. Write-Host "[SKIP] No BackgroundDownload processes currently running" -ForegroundColor $Colors.Gray
  215. return $false
  216. }
  217. } catch {
  218. Write-Host "[ERROR] Error checking processes: $_" -ForegroundColor $Colors.Error
  219. return $false
  220. }
  221. }
  222. function Remove-BackgroundDownloadTempFolders {
  223. Write-Host "[INFO] Cleaning BackgroundDownload temporary folders..." -ForegroundColor $Colors.Info
  224. try {
  225. $tempPaths = @(
  226. "$env:TEMP",
  227. "$env:LOCALAPPDATA\Temp"
  228. )
  229. $foldersRemoved = 0
  230. foreach ($tempPath in $tempPaths) {
  231. if (Test-Path $tempPath) {
  232. $folders = Get-ChildItem -Path $tempPath -Directory -ErrorAction SilentlyContinue |
  233. Where-Object { $_.Name -match "^[a-zA-Z0-9]{8}\." }
  234. foreach ($folder in $folders) {
  235. $bgDownloadPath = Join-Path $folder.FullName "resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service\BackgroundDownload.exe"
  236. if (Test-Path $bgDownloadPath) {
  237. try {
  238. Remove-Item -Path $folder.FullName -Recurse -Force -ErrorAction Stop
  239. Write-Host "[OK] Removed temp folder: $($folder.Name)" -ForegroundColor $Colors.Success
  240. $foldersRemoved++
  241. }
  242. catch {
  243. Write-Host "[ERROR] Could not remove folder $($folder.Name): $_" -ForegroundColor $Colors.Error
  244. }
  245. }
  246. }
  247. }
  248. }
  249. if ($foldersRemoved -eq 0) {
  250. Write-Host "[SKIP] No BackgroundDownload temp folders found" -ForegroundColor $Colors.Gray
  251. }
  252. return $foldersRemoved -gt 0
  253. } catch {
  254. Write-Host "[ERROR] Error cleaning temp folders: $_" -ForegroundColor $Colors.Error
  255. return $false
  256. }
  257. }
  258. function Set-SafeEnvironmentVariable {
  259. param(
  260. [string]$Name,
  261. [string]$Value,
  262. [string]$Target = 'User'
  263. )
  264. try {
  265. $currentValue = [Environment]::GetEnvironmentVariable($Name, $Target)
  266. if ($currentValue -eq $Value) {
  267. Write-Host "[OK] $Name already set to $Value" -ForegroundColor $Colors.Success
  268. } else {
  269. [Environment]::SetEnvironmentVariable($Name, $Value, $Target)
  270. Write-Host "[OK] Set $Name to $Value" -ForegroundColor $Colors.Success
  271. }
  272. return $true
  273. }
  274. catch {
  275. Write-Host "[ERROR] Failed to set environment variable $Name : $_" -ForegroundColor $Colors.Error
  276. return $false
  277. }
  278. }
  279. # =======================================================
  280. # MAIN SCRIPT LOGIC
  281. # =======================================================
  282. # Handle backup/restore operations
  283. if ($RestoreBackup) {
  284. $null = Restore-RegistryBackup -BackupFile $BackupPath
  285. Write-Host "`nRestore operation completed. Press Enter to exit..." -ForegroundColor $Colors.Info
  286. $null = Read-Host
  287. exit
  288. }
  289. if ($CreateBackup) {
  290. $null = New-RegistryBackup -BackupFile $BackupPath
  291. Write-Host "`nBackup created at: $BackupPath" -ForegroundColor $Colors.Info
  292. Write-Host "You can restore with: .\off_telemetry_ps5.ps1 -RestoreBackup -BackupPath '$BackupPath'" -ForegroundColor $Colors.Info
  293. $continue = Read-Host "`nContinue with telemetry disable? (y/n)"
  294. if ($continue -ne 'y' -and $continue -ne 'Y') {
  295. exit
  296. }
  297. }
  298. # =======================================================
  299. # DETECT INSTALLED VISUAL STUDIO VERSIONS
  300. # =======================================================
  301. Write-Host "`n--- Detecting Installed Visual Studio Versions ---" -ForegroundColor $Colors.Section
  302. $vsVersions = @{
  303. "14.0" = "Visual Studio 2015"
  304. "15.0" = "Visual Studio 2017"
  305. "16.0" = "Visual Studio 2019"
  306. "17.0" = "Visual Studio 2022"
  307. }
  308. $installedVersions = @()
  309. foreach ($version in $vsVersions.Keys) {
  310. $vsName = $vsVersions[$version]
  311. # Check multiple detection methods
  312. $detected = $false
  313. # Method 1: Registry SQM paths
  314. $paths = @(
  315. "HKLM:\SOFTWARE\Microsoft\VSCommon\$version",
  316. "HKLM:\SOFTWARE\Wow6432Node\Microsoft\VSCommon\$version"
  317. )
  318. foreach ($path in $paths) {
  319. if (Test-Path $path) {
  320. $detected = $true
  321. break
  322. }
  323. }
  324. # Method 2: Installation paths
  325. if (!$detected) {
  326. $installPaths = @(
  327. "${env:ProgramFiles}\Microsoft Visual Studio\*\*\Common7\IDE\devenv.exe",
  328. "${env:ProgramFiles(x86)}\Microsoft Visual Studio\*\*\Common7\IDE\devenv.exe",
  329. "${env:ProgramFiles(x86)}\Microsoft Visual Studio $version\*\Common7\IDE\devenv.exe"
  330. )
  331. foreach ($installPath in $installPaths) {
  332. if (Get-ChildItem -Path $installPath -ErrorAction SilentlyContinue) {
  333. $detected = $true
  334. break
  335. }
  336. }
  337. }
  338. if ($detected) {
  339. Write-Host "[OK] Detected: $vsName (version $version)" -ForegroundColor $Colors.Success
  340. $installedVersions += $version
  341. } else {
  342. Write-Host "[SKIP] Not found: $vsName (version $version)" -ForegroundColor $Colors.Gray
  343. }
  344. }
  345. if ($installedVersions.Count -eq 0) {
  346. Write-Host "[INFO] No Visual Studio installations detected" -ForegroundColor $Colors.Info
  347. }
  348. # =======================================================
  349. # VISUAL STUDIO TELEMETRY DISABLE (EXISTING INSTALLATIONS ONLY)
  350. # =======================================================
  351. Write-Host "`n--- Disabling Visual Studio Telemetry (Detected Installations) ---" -ForegroundColor $Colors.Section
  352. foreach ($version in $installedVersions) {
  353. $vsName = $vsVersions[$version]
  354. Write-Host "`n--- Processing $vsName (version $version) ---" -ForegroundColor $Colors.Info
  355. # Process both architectures
  356. $regPaths = @()
  357. if ([Environment]::Is64BitOperatingSystem) {
  358. $regPaths += "HKLM:\SOFTWARE\Wow6432Node\Microsoft\VSCommon\$version\SQM"
  359. }
  360. $regPaths += "HKLM:\SOFTWARE\Microsoft\VSCommon\$version\SQM"
  361. foreach ($regPath in $regPaths) {
  362. $null = Set-SafeRegistryValue -Path $regPath -Name "OptIn" -Value 0 -Type 'DWORD'
  363. }
  364. # Additional paths for this version
  365. $additionalPaths = @(
  366. "HKCU:\Software\Microsoft\VisualStudio\$version\General"
  367. )
  368. foreach ($path in $additionalPaths) {
  369. $null = Set-SafeRegistryValue -Path $path -Name "EnableSQM" -Value 0 -Type 'DWORD'
  370. }
  371. }
  372. # =======================================================
  373. # VISUAL STUDIO POLICY SETTINGS (CONSERVATIVE APPROACH)
  374. # =======================================================
  375. Write-Host "`n--- Checking Visual Studio Policy Settings ---" -ForegroundColor $Colors.Section
  376. # Only create policy paths if at least one VS version is installed
  377. if ($installedVersions.Count -gt 0) {
  378. Write-Host "[INFO] Visual Studio detected, configuring policies..." -ForegroundColor $Colors.Info
  379. # Policy paths (create only if VS is installed)
  380. $policyPaths = @{
  381. "HKLM:\SOFTWARE\Policies\Microsoft\VisualStudio\Feedback" = @{
  382. "DisableFeedbackDialog" = 1
  383. "DisableEmailInput" = 1
  384. "DisableScreenshotCapture" = 1
  385. }
  386. "HKLM:\SOFTWARE\Policies\Microsoft\VisualStudio\SQM" = @{
  387. "OptIn" = 0
  388. }
  389. "HKCU:\Software\Microsoft\VisualStudio\Telemetry" = @{
  390. "TurnOffSwitch" = 1
  391. }
  392. }
  393. foreach ($path in $policyPaths.Keys) {
  394. $settings = $policyPaths[$path]
  395. foreach ($setting in $settings.GetEnumerator()) {
  396. $null = Set-SafeRegistryValue -Path $path -Name $setting.Key -Value $setting.Value -Type 'DWORD' -CreatePath
  397. }
  398. }
  399. } else {
  400. Write-Host "[SKIP] No Visual Studio detected, skipping policy configuration" -ForegroundColor $Colors.Gray
  401. }
  402. # =======================================================
  403. # EXPERIENCE IMPROVEMENT PROGRAM
  404. # =======================================================
  405. Write-Host "`n--- Disabling Customer Experience Improvement Program ---" -ForegroundColor $Colors.Section
  406. $experiencePaths = @(
  407. "HKLM:\SOFTWARE\Microsoft\SQMClient",
  408. "HKLM:\SOFTWARE\Wow6432Node\Microsoft\SQMClient"
  409. )
  410. foreach ($path in $experiencePaths) {
  411. $null = Set-SafeRegistryValue -Path $path -Name "CEIPEnable" -Value 0 -Type 'DWORD'
  412. }
  413. # =======================================================
  414. # TELEMETRY DIRECTORIES CLEANUP
  415. # =======================================================
  416. Write-Host "`n--- Cleaning Telemetry Directories ---" -ForegroundColor $Colors.Section
  417. $telemetryDirs = @(
  418. "$env:APPDATA\vstelemetry",
  419. "$env:LOCALAPPDATA\Microsoft\VSApplicationInsights",
  420. "$env:PROGRAMDATA\Microsoft\VSApplicationInsights",
  421. "$env:TEMP\Microsoft\VSApplicationInsights",
  422. "$env:TEMP\VSFaultInfo",
  423. "$env:TEMP\VSFeedbackIntelliCodeLogs",
  424. "$env:TEMP\VSFeedbackPerfWatsonData",
  425. "$env:TEMP\VSFeedbackVSRTCLogs",
  426. "$env:TEMP\VSRemoteControl",
  427. "$env:TEMP\VSTelem",
  428. "$env:TEMP\VSTelem.Out"
  429. )
  430. foreach ($dir in $telemetryDirs) {
  431. Remove-TelemetryDirectory -Path $dir
  432. }
  433. # =======================================================
  434. # .NET AND NUGET TELEMETRY DISABLE
  435. # =======================================================
  436. Write-Host "`n--- Disabling .NET and NuGet Telemetry ---" -ForegroundColor $Colors.Section
  437. $null = Set-SafeEnvironmentVariable -Name 'DOTNET_CLI_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  438. $null = Set-SafeEnvironmentVariable -Name 'NUGET_TELEMETRY_OPTOUT' -Value 'true' -Target 'User'
  439. # =======================================================
  440. # VISUAL STUDIO STANDARD COLLECTOR SERVICE
  441. # =======================================================
  442. Write-Host "`n--- Managing VS Standard Collector Service ---" -ForegroundColor $Colors.Section
  443. $serviceName = 'VSStandardCollectorService150'
  444. $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
  445. if ($service) {
  446. Write-Host "[INFO] Found service: $serviceName" -ForegroundColor $Colors.Info
  447. # Stop service if running
  448. if ($service.Status -eq 'Running') {
  449. try {
  450. Stop-Service -Name $serviceName -Force -ErrorAction Stop
  451. Write-Host "[OK] Stopped $serviceName" -ForegroundColor $Colors.Success
  452. }
  453. catch {
  454. Write-Host "[ERROR] Could not stop $serviceName : $_" -ForegroundColor $Colors.Error
  455. }
  456. } else {
  457. Write-Host "[INFO] Service $serviceName already stopped (Status: $($service.Status))" -ForegroundColor $Colors.Info
  458. }
  459. # Disable service
  460. if ($service.StartType -eq 'Disabled') {
  461. Write-Host "[OK] $serviceName already disabled" -ForegroundColor $Colors.Success
  462. } else {
  463. try {
  464. Set-Service -Name $serviceName -StartupType Disabled -Confirm:$false -ErrorAction Stop
  465. Write-Host "[OK] Disabled $serviceName" -ForegroundColor $Colors.Success
  466. }
  467. catch {
  468. Write-Host "[ERROR] Could not disable $serviceName : $_" -ForegroundColor $Colors.Error
  469. }
  470. }
  471. } else {
  472. Write-Host "[SKIP] $serviceName not found (not installed)" -ForegroundColor $Colors.Gray
  473. }
  474. $serviceProcessed = ($null -ne $service)
  475. # =======================================================
  476. # VISUAL STUDIO CODE SETTINGS
  477. # =======================================================
  478. Write-Host "`n--- Configuring Visual Studio Code Settings ---" -ForegroundColor $Colors.Section
  479. $vscodeSettings = "$env:APPDATA\Code\User\settings.json"
  480. $vscodeUserDir = "$env:APPDATA\Code\User"
  481. $vscodeDetected = $false
  482. if (!(Test-Path "$env:APPDATA\Code")) {
  483. Write-Host "[SKIP] Visual Studio Code not detected" -ForegroundColor $Colors.Gray
  484. } else {
  485. Write-Host "[INFO] Visual Studio Code detected" -ForegroundColor $Colors.Info
  486. $vscodeDetected = $true
  487. # Create User directory if needed
  488. if (!(Test-Path $vscodeUserDir)) {
  489. try {
  490. $null = New-Item -Path $vscodeUserDir -ItemType Directory -Force
  491. Write-Host "[INFO] Created VS Code User directory" -ForegroundColor $Colors.Info
  492. } catch {
  493. Write-Host "[ERROR] Failed to create VS Code User directory: $_" -ForegroundColor $Colors.Error
  494. }
  495. }
  496. # Privacy settings
  497. $privacyConfig = @{
  498. "telemetry.enableTelemetry" = $false
  499. "telemetry.enableCrashReporter" = $false
  500. "workbench.enableExperiments" = $false
  501. "update.mode" = "manual"
  502. "update.showReleaseNotes" = $false
  503. "extensions.autoCheckUpdates" = $false
  504. "extensions.showRecommendationsOnlyOnDemand" = $true
  505. "git.autofetch" = $false
  506. "npm.fetchOnlinePackageInfo" = $false
  507. }
  508. try {
  509. # Load existing settings
  510. $settings = @{}
  511. if (Test-Path $vscodeSettings) {
  512. $content = Get-Content $vscodeSettings -Raw -ErrorAction SilentlyContinue
  513. if ($content -and $content.Trim()) {
  514. try {
  515. # Use PowerShell's built-in JSON cmdlets
  516. $settingsObj = $content | ConvertFrom-Json
  517. # Convert PSCustomObject to hashtable for easier manipulation
  518. $settings = @{}
  519. $settingsObj.PSObject.Properties | ForEach-Object {
  520. $settings[$_.Name] = $_.Value
  521. }
  522. Write-Host "[INFO] Found existing VS Code settings file" -ForegroundColor $Colors.Info
  523. }
  524. catch {
  525. Write-Host "> Could not parse existing settings, creating new ones" -ForegroundColor $Colors.Warning
  526. $settings = @{}
  527. }
  528. }
  529. }
  530. # Update settings
  531. $changesMade = $false
  532. foreach ($key in $privacyConfig.Keys) {
  533. $value = $privacyConfig[$key]
  534. if ($settings.ContainsKey($key) -and $settings[$key] -eq $value) {
  535. Write-Host "[OK] $key already set to $value" -ForegroundColor $Colors.Success
  536. } else {
  537. $settings[$key] = $value
  538. Write-Host "[OK] Updated $key to $value" -ForegroundColor $Colors.Success
  539. $changesMade = $true
  540. }
  541. }
  542. # Save settings if changes were made
  543. if ($changesMade -or !(Test-Path $vscodeSettings)) {
  544. $json = $settings | ConvertTo-Json -Depth 10
  545. $json | Out-File -FilePath $vscodeSettings -Encoding UTF8
  546. Write-Host "[OK] Saved VS Code privacy settings" -ForegroundColor $Colors.Success
  547. } else {
  548. Write-Host "[INFO] No changes needed for VS Code settings" -ForegroundColor $Colors.Info
  549. }
  550. }
  551. catch {
  552. Write-Host "[ERROR] Failed to update VS Code settings: $_" -ForegroundColor $Colors.Error
  553. }
  554. }
  555. # =======================================================
  556. # VISUAL STUDIO BACKGROUND DOWNLOAD DISABLE
  557. # =======================================================
  558. Write-Host "`n--- Disabling Visual Studio Background Download ---" -ForegroundColor $Colors.Section
  559. $backgroundDownloadProcessed = $false
  560. # Check if any Visual Studio versions are installed before proceeding
  561. if ($installedVersions.Count -gt 0) {
  562. Write-Host "[INFO] Visual Studio detected, processing BackgroundDownload settings..." -ForegroundColor $Colors.Info
  563. # 1. Disable scheduled tasks
  564. $tasksProcessed = Disable-BackgroundDownloadTasks
  565. # 2. Set registry keys to disable background downloads
  566. Write-Host "[INFO] Setting registry keys to disable background downloads..." -ForegroundColor $Colors.Info
  567. $regPaths = @(
  568. "HKLM:\SOFTWARE\Microsoft\VisualStudio\Setup",
  569. "HKLM:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\Setup"
  570. )
  571. $regKeysSet = $false
  572. foreach ($regPath in $regPaths) {
  573. # Check if this registry path should exist (based on architecture)
  574. $shouldProcess = $true
  575. if ($regPath -like "*Wow6432Node*" -and ![Environment]::Is64BitOperatingSystem) {
  576. $shouldProcess = $false
  577. }
  578. if ($shouldProcess) {
  579. # Create the registry path if it doesn't exist (since we're configuring VS Setup)
  580. if (!(Test-Path $regPath)) {
  581. try {
  582. $null = New-Item -Path $regPath -Force -ErrorAction Stop
  583. Write-Host "[INFO] Created registry path: $regPath" -ForegroundColor $Colors.Info
  584. }
  585. catch {
  586. Write-Host "[ERROR] Could not create registry path $regPath : $_" -ForegroundColor $Colors.Error
  587. continue
  588. }
  589. }
  590. # Set the registry values
  591. $regSettings = @{
  592. "BackgroundDownloadDisabled" = 1
  593. "DisableBackgroundDownloads" = 1
  594. "DisableAutomaticUpdates" = 1
  595. }
  596. foreach ($setting in $regSettings.GetEnumerator()) {
  597. $success = Set-SafeRegistryValue -Path $regPath -Name $setting.Key -Value $setting.Value -Type 'DWORD'
  598. if ($success) {
  599. $regKeysSet = $true
  600. }
  601. }
  602. }
  603. }
  604. # 3. Stop running processes
  605. $processesProcessed = Stop-BackgroundDownloadProcesses
  606. # 4. Clean temporary folders
  607. $tempFoldersProcessed = Remove-BackgroundDownloadTempFolders
  608. # 5. Verification
  609. Write-Host "[INFO] Verifying BackgroundDownload configuration..." -ForegroundColor $Colors.Info
  610. try {
  611. $verificationSuccess = $false
  612. # Check registry settings
  613. foreach ($regPath in $regPaths) {
  614. if (Test-Path $regPath) {
  615. $regValues = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue
  616. if ($regValues -and $regValues.BackgroundDownloadDisabled -eq 1) {
  617. Write-Host "[OK] Registry verification: BackgroundDownloadDisabled = 1 in $regPath" -ForegroundColor $Colors.Success
  618. $verificationSuccess = $true
  619. }
  620. }
  621. }
  622. if (!$verificationSuccess) {
  623. Write-Host "[WARNING] Could not verify registry settings" -ForegroundColor $Colors.Warning
  624. }
  625. } catch {
  626. Write-Host "[WARNING] Verification error: $_" -ForegroundColor $Colors.Warning
  627. }
  628. # Set processed flag if any operation was successful
  629. $backgroundDownloadProcessed = $tasksProcessed -or $regKeysSet -or $processesProcessed -or $tempFoldersProcessed
  630. } else {
  631. Write-Host "[SKIP] No Visual Studio installations detected, skipping BackgroundDownload configuration" -ForegroundColor $Colors.Gray
  632. }
  633. # =======================================================
  634. # POWERSHELL TELEMETRY [off] FOR PS 7.x
  635. # =======================================================
  636. Write-Host "`n--- Disabling PowerShell Telemetry ---" -ForegroundColor $Colors.Section
  637. # Check Windows version
  638. $powershellTelemetryProcessed = $false
  639. try {
  640. $osVersion = [System.Environment]::OSVersion.Version
  641. $windowsVersion = "$($osVersion.Major).$($osVersion.Minor)"
  642. # Windows version mapping:
  643. # Windows 7: 6.1
  644. # Windows 8: 6.2
  645. # Windows 8.1: 6.3
  646. # Windows 10: 10.0
  647. # Windows 11: 10.0 (build 22000+)
  648. $isWindows8Plus = ($osVersion.Major -gt 6) -or ($osVersion.Major -eq 6 -and $osVersion.Minor -ge 2)
  649. if ($isWindows8Plus) {
  650. Write-Host "[INFO] Windows version $windowsVersion detected (Windows 8+)" -ForegroundColor $Colors.Info
  651. $null = Set-SafeEnvironmentVariable -Name 'POWERSHELL_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  652. $powershellTelemetryProcessed = $true
  653. } else {
  654. Write-Host "[SKIP] Windows version $windowsVersion detected (Windows 7), skipping PowerShell telemetry disable" -ForegroundColor $Colors.Gray
  655. Write-Host "[INFO] PowerShell telemetry disable is only applied on Windows 8 and newer" -ForegroundColor $Colors.Info
  656. }
  657. }
  658. catch {
  659. Write-Host "[ERROR] Could not detect Windows version: $_" -ForegroundColor $Colors.Error
  660. Write-Host "[INFO] Attempting to disable PowerShell telemetry anyway..." -ForegroundColor $Colors.Info
  661. $null = Set-SafeEnvironmentVariable -Name 'POWERSHELL_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  662. $powershellTelemetryProcessed = $true
  663. }
  664. # =======================================================
  665. # SUMMARY
  666. # =======================================================
  667. Write-Host "`n========================================" -ForegroundColor $Colors.Title
  668. Write-Host "TELEMETRY DISABLE COMPLETE" -ForegroundColor $Colors.Title
  669. Write-Host "========================================" -ForegroundColor $Colors.Title
  670. Write-Host "`nProcessed telemetry settings for:" -ForegroundColor White
  671. # Visual Studio versions with status colors
  672. if ($installedVersions.Count -gt 0) {
  673. foreach ($version in $installedVersions) {
  674. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  675. Write-Host "$($vsVersions[$version]) (detected)" -ForegroundColor $Colors.Success
  676. }
  677. } else {
  678. Write-Host "[SKIP] " -NoNewline -ForegroundColor $Colors.Gray
  679. Write-Host "No Visual Studio versions detected" -ForegroundColor $Colors.Gray
  680. }
  681. # Visual Studio Code with status colors
  682. if ($vscodeDetected) {
  683. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  684. Write-Host "Visual Studio Code (detected)" -ForegroundColor $Colors.Success
  685. } else {
  686. Write-Host "[SKIP] " -NoNewline -ForegroundColor $Colors.Gray
  687. Write-Host "Visual Studio Code (not found)" -ForegroundColor $Colors.Gray
  688. }
  689. # Other components with status indicators
  690. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  691. Write-Host ".NET CLI" -ForegroundColor $Colors.Success
  692. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  693. Write-Host "NuGet" -ForegroundColor $Colors.Success
  694. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  695. Write-Host "Settings Synchronization" -ForegroundColor $Colors.Success
  696. # VS Standard Collector Service status
  697. if ($serviceProcessed) {
  698. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  699. Write-Host "VS Standard Collector Service (processed)" -ForegroundColor $Colors.Success
  700. } else {
  701. Write-Host "[SKIP] " -NoNewline -ForegroundColor $Colors.Gray
  702. Write-Host "VS Standard Collector Service (not found)" -ForegroundColor $Colors.Gray
  703. }
  704. # Visual Studio Background Download status
  705. if ($backgroundDownloadProcessed) {
  706. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  707. Write-Host "Visual Studio Background Download (disabled)" -ForegroundColor $Colors.Success
  708. } else {
  709. Write-Host "[SKIP] " -NoNewline -ForegroundColor $Colors.Gray
  710. Write-Host "Visual Studio Background Download (not processed)" -ForegroundColor $Colors.Gray
  711. }
  712. # PowerShell Telemetry status
  713. if ($powershellTelemetryProcessed) {
  714. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  715. Write-Host "PowerShell 7 Telemetry (disabled)" -ForegroundColor $Colors.Success
  716. } else {
  717. Write-Host "[SKIP] " -NoNewline -ForegroundColor $Colors.Gray
  718. Write-Host "PowerShell 7 Telemetry (Windows 7 - not supported)" -ForegroundColor $Colors.Gray
  719. }
  720. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  721. Write-Host "Customer Experience Improvement Program" -ForegroundColor $Colors.Success
  722. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success
  723. Write-Host "Telemetry Directories Cleanup" -ForegroundColor $Colors.Success
  724. # =======================================================
  725. # ADDITIONAL FEATURES AND ENVIRONMENT VARIABLES
  726. # =======================================================
  727. Write-Host "`n--- Optional: Additional Features and Environment Variables ---" -ForegroundColor $Colors.Section
  728. Write-Host "This will perform additional configuration:" -ForegroundColor $Colors.Info
  729. Write-Host "> Disable Visual Studio Settings Synchronization" -ForegroundColor $Colors.Info
  730. Write-Host "> Disable Live Share" -ForegroundColor $Colors.Info
  731. Write-Host "> Disable IntelliCode" -ForegroundColor $Colors.Info
  732. Write-Host "> Disable CodeLens" -ForegroundColor $Colors.Info
  733. Write-Host "> Set additional environment variables :" -ForegroundColor $Colors.Info
  734. Write-Host " - INTELLICODE_TELEMETRY_OPTOUT" -ForegroundColor $Colors.Info
  735. Write-Host " - LIVESHARE_TELEMETRY_OPTOUT" -ForegroundColor $Colors.Info
  736. Write-Host " - VSSDK_TELEMETRY_OPTOUT" -ForegroundColor $Colors.Info
  737. $enableAdditional = Read-Host "`nEnable additional configuration? (y/n)"
  738. if ($enableAdditional -eq 'y' -or $enableAdditional -eq 'Y' -or $enableAdditional -eq 'yes' -or $enableAdditional -eq 'Yes' -or $enableAdditional -eq 'YES') {
  739. # =======================================================
  740. # VISUAL STUDIO ADDITIONAL FEATURES DISABLE
  741. # =======================================================
  742. Write-Host "`n--- Disabling Additional Visual Studio Features ---" -ForegroundColor $Colors.Section
  743. if ($installedVersions.Count -gt 0) {
  744. foreach ($version in $installedVersions) {
  745. $vsName = $vsVersions[$version]
  746. Write-Host "`n--- Processing Additional Features for $vsName (version $version) ---" -ForegroundColor $Colors.Info
  747. # =======================================================
  748. # SETTINGS SYNCHRONIZATION
  749. # =======================================================
  750. Write-Host "[INFO] Disabling Settings Synchronization..." -ForegroundColor $Colors.Info
  751. $settingsPaths = @(
  752. "HKCU:\Software\Microsoft\VisualStudio\$version\Settings",
  753. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\Settings"
  754. )
  755. foreach ($path in $settingsPaths) {
  756. $null = Set-SafeRegistryValue -Path $path -Name "SyncSettings" -Value 0 -Type 'DWORD' -CreatePath
  757. $null = Set-SafeRegistryValue -Path $path -Name "EnableRoaming" -Value 0 -Type 'DWORD' -CreatePath
  758. $null = Set-SafeRegistryValue -Path $path -Name "EnableSync" -Value 0 -Type 'DWORD' -CreatePath
  759. $null = Set-SafeRegistryValue -Path $path -Name "DisableSync" -Value 1 -Type 'DWORD' -CreatePath
  760. }
  761. # Additional settings sync paths
  762. $syncPath = "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\ConnectedServices"
  763. $null = Set-SafeRegistryValue -Path $syncPath -Name "Provider.Enabled" -Value 0 -Type 'DWORD' -CreatePath
  764. # =======================================================
  765. # LIVE SHARE
  766. # =======================================================
  767. Write-Host "[INFO] Disabling Live Share..." -ForegroundColor $Colors.Info
  768. $liveSharePaths = @(
  769. "HKCU:\Software\Microsoft\VisualStudio\$version\LiveShare",
  770. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\LiveShare"
  771. )
  772. foreach ($path in $liveSharePaths) {
  773. $null = Set-SafeRegistryValue -Path $path -Name "Enabled" -Value 0 -Type 'DWORD' -CreatePath
  774. $null = Set-SafeRegistryValue -Path $path -Name "EnableTelemetry" -Value 0 -Type 'DWORD' -CreatePath
  775. $null = Set-SafeRegistryValue -Path $path -Name "DisableTelemetry" -Value 1 -Type 'DWORD' -CreatePath
  776. $null = Set-SafeRegistryValue -Path $path -Name "OptedIn" -Value 0 -Type 'DWORD' -CreatePath
  777. }
  778. # Live Share telemetry
  779. $liveShareTelemetryPath = "HKCU:\Software\Microsoft\VisualStudio\$version\LiveShare\Telemetry"
  780. $null = Set-SafeRegistryValue -Path $liveShareTelemetryPath -Name "Enabled" -Value 0 -Type 'DWORD' -CreatePath
  781. $null = Set-SafeRegistryValue -Path $liveShareTelemetryPath -Name "OptOut" -Value 1 -Type 'DWORD' -CreatePath
  782. # =======================================================
  783. # INTELLICODE
  784. # =======================================================
  785. Write-Host "[INFO] Disabling IntelliCode..." -ForegroundColor $Colors.Info
  786. $intelliCodePaths = @(
  787. "HKCU:\Software\Microsoft\VisualStudio\$version\IntelliCode",
  788. "HKCU:\Software\Microsoft\VisualStudio\$version\IntelliSense\IntelliCode",
  789. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\IntelliCode"
  790. )
  791. foreach ($path in $intelliCodePaths) {
  792. $null = Set-SafeRegistryValue -Path $path -Name "DisableTelemetry" -Value 1 -Type 'DWORD' -CreatePath
  793. $null = Set-SafeRegistryValue -Path $path -Name "EnableTelemetry" -Value 0 -Type 'DWORD' -CreatePath
  794. $null = Set-SafeRegistryValue -Path $path -Name "OptedIn" -Value 0 -Type 'DWORD' -CreatePath
  795. $null = Set-SafeRegistryValue -Path $path -Name "Enabled" -Value 0 -Type 'DWORD' -CreatePath
  796. $null = Set-SafeRegistryValue -Path $path -Name "ModelDownloadEnabled" -Value 0 -Type 'DWORD' -CreatePath
  797. }
  798. # IntelliCode privacy settings
  799. $intelliCodePrivacyPath = "HKCU:\Software\Microsoft\VisualStudio\$version\IntelliCode\Privacy"
  800. $null = Set-SafeRegistryValue -Path $intelliCodePrivacyPath -Name "TelemetryOptOut" -Value 1 -Type 'DWORD' -CreatePath
  801. $null = Set-SafeRegistryValue -Path $intelliCodePrivacyPath -Name "DataCollection" -Value 0 -Type 'DWORD' -CreatePath
  802. $null = Set-SafeRegistryValue -Path $intelliCodePrivacyPath -Name "UsageDataOptOut" -Value 1 -Type 'DWORD' -CreatePath
  803. # =======================================================
  804. # CODELENS
  805. # =======================================================
  806. Write-Host "[INFO] Disabling CodeLens..." -ForegroundColor $Colors.Info
  807. $codeLensPaths = @(
  808. "HKCU:\Software\Microsoft\VisualStudio\$version\CodeLens",
  809. "HKCU:\Software\Microsoft\VisualStudio\$version\TextEditor\CodeLens",
  810. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\CodeLens"
  811. )
  812. foreach ($path in $codeLensPaths) {
  813. $null = Set-SafeRegistryValue -Path $path -Name "Disabled" -Value 1 -Type 'DWORD' -CreatePath
  814. $null = Set-SafeRegistryValue -Path $path -Name "ShowAuthorCodeLens" -Value 0 -Type 'DWORD' -CreatePath
  815. $null = Set-SafeRegistryValue -Path $path -Name "ShowReferencesCodeLens" -Value 0 -Type 'DWORD' -CreatePath
  816. $null = Set-SafeRegistryValue -Path $path -Name "ShowTestCodeLens" -Value 0 -Type 'DWORD' -CreatePath
  817. $null = Set-SafeRegistryValue -Path $path -Name "Enabled" -Value 0 -Type 'DWORD' -CreatePath
  818. }
  819. # CodeLens telemetry
  820. $codeLensTelemetryPath = "HKCU:\Software\Microsoft\VisualStudio\$version\CodeLens\Telemetry"
  821. $null = Set-SafeRegistryValue -Path $codeLensTelemetryPath -Name "Enabled" -Value 0 -Type 'DWORD' -CreatePath
  822. $null = Set-SafeRegistryValue -Path $codeLensTelemetryPath -Name "OptOut" -Value 1 -Type 'DWORD' -CreatePath
  823. }
  824. } else {
  825. Write-Host "[SKIP] No Visual Studio installations detected, skipping additional features" -ForegroundColor $Colors.Gray
  826. }
  827. # =======================================================
  828. # ADDITIONAL ENVIRONMENT VARIABLES
  829. # =======================================================
  830. Write-Host "`n--- Setting Additional Environment Variables ---" -ForegroundColor $Colors.Section
  831. $null = Set-SafeEnvironmentVariable -Name 'INTELLICODE_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  832. $null = Set-SafeEnvironmentVariable -Name 'LIVESHARE_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  833. $null = Set-SafeEnvironmentVariable -Name 'VSSDK_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  834. Write-Host "`n[OK] Additional configuration completed" -ForegroundColor $Colors.Success
  835. } else {
  836. Write-Host "[SKIP] Skipping additional configuration" -ForegroundColor $Colors.Info
  837. }
  838. Write-Host "`nLegend:" -ForegroundColor White
  839. Write-Host "[OK] " -NoNewline -ForegroundColor $Colors.Success; Write-Host "Action completed successfully"
  840. Write-Host "[INFO] " -NoNewline -ForegroundColor $Colors.Info; Write-Host "Information or preparatory action"
  841. Write-Host "[SKIP] " -NoNewline -ForegroundColor $Colors.Gray; Write-Host "Component not found, skipped"
  842. Write-Host "[ERROR] " -NoNewline -ForegroundColor $Colors.Error; Write-Host "Error occurred"
  843. if (!$CreateBackup) {
  844. Write-Host "`nTip: Run with -CreateBackup parameter to create registry backup first" -ForegroundColor $Colors.Warning
  845. }
  846. Write-Host "`nRestart may be required for all changes to take effect." -ForegroundColor $Colors.Warning
  847. Write-Host "Press Enter to exit..." -ForegroundColor White
  848. $null = Read-Host