off_telemetry_ps7.ps1 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. using namespace System.Collections.Generic
  2. <#
  3. .SYNOPSIS
  4. Enhanced comprehensive script to disable telemetry in Microsoft development tools with backup/restore functionality
  5. .DESCRIPTION
  6. This script disables telemetry, crash reporting, and data collection for:
  7. - Visual Studio 2015-2022 (only if installed)
  8. - Visual Studio Code (only if installed)
  9. - .NET CLI
  10. - NuGet
  11. - Various Visual Studio services
  12. .NOTES
  13. Must be run as Administrator
  14. Only modifies existing registry paths - does not create new ones
  15. Requires PowerShell 7.0+
  16. Includes comprehensive backup and restore functionality
  17. .PARAMETER CreateBackup
  18. Creates registry backup before making changes
  19. .PARAMETER RestoreBackup
  20. Restores registry from backup file
  21. .PARAMETER BackupPath
  22. Path for backup file (default: Desktop with timestamp)
  23. .EXAMPLE
  24. .\off_telemetry_ps7.ps1 -CreateBackup
  25. .\off_telemetry_ps7.ps1 -RestoreBackup -BackupPath "C:\Backup\registry_backup.reg"
  26. .\off_telemetry_ps7.ps1 -CreateBackup -BackupPath "C:\MyBackups\telemetry_backup.reg"
  27. #>
  28. param(
  29. [switch]$CreateBackup,
  30. [switch]$RestoreBackup,
  31. [string]$BackupPath = "$env:USERPROFILE\Desktop\telemetry_backup_$(Get-Date -Format 'yyyyMMdd_HHmmss').reg"
  32. )
  33. # Color scheme for consistent output
  34. $Colors = @{
  35. Title = 'Cyan'
  36. Section = 'Yellow'
  37. Success = 'Green'
  38. Info = 'Blue'
  39. Warning = 'Yellow'
  40. Error = 'Red'
  41. Gray = 'Gray'
  42. White = 'White'
  43. }
  44. Write-Host "======================================================" -ForegroundColor $Colors.Title
  45. Write-Host " by EXLOUD aka BOBER" -ForegroundColor $Colors.Title
  46. Write-Host "======================================================" -ForegroundColor $Colors.Title
  47. # =======================================================
  48. # BACKUP AND RESTORE FUNCTIONS
  49. # =======================================================
  50. function New-RegistryBackup {
  51. <#
  52. .SYNOPSIS
  53. Creates backup of telemetry-related registry keys
  54. .PARAMETER BackupFile
  55. Path where backup file will be created
  56. #>
  57. param([string]$BackupFile)
  58. Write-Host "`n--- Creating Registry Backup ---" -ForegroundColor $Colors.Section
  59. try {
  60. # Ensure backup directory exists
  61. $backupDir = Split-Path -Path $BackupFile -Parent
  62. if (!(Test-Path $backupDir)) {
  63. New-Item -Path $backupDir -ItemType Directory -Force | Out-Null
  64. Write-Host "→ Created backup directory: $backupDir" -ForegroundColor $Colors.Info
  65. }
  66. # Registry keys to backup
  67. $backupKeys = [ordered]@{
  68. "VSCommon_x64" = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VSCommon"
  69. "VSCommon_x86" = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VSCommon"
  70. "VSPolicies" = "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\VisualStudio"
  71. "VSUser" = "HKEY_CURRENT_USER\Software\Microsoft\VisualStudio"
  72. "SQMClient_x64" = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQMClient"
  73. "SQMClient_x86" = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\SQMClient"
  74. }
  75. $backupCount = 0
  76. $backupContent = @()
  77. # Add header to backup file
  78. $backupContent += "Windows Registry Editor Version 5.00"
  79. $backupContent += ""
  80. $backupContent += "; Telemetry Registry Backup created on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
  81. $backupContent += "; Generated by Enhanced Telemetry Manager for PowerShell 7.0+"
  82. $backupContent += ""
  83. foreach ($keyInfo in $backupKeys.GetEnumerator()) {
  84. $keyName = $keyInfo.Key
  85. $keyPath = $keyInfo.Value
  86. Write-Host "→ Checking registry key: $keyName" -ForegroundColor $Colors.Info
  87. # Use reg.exe to export individual keys
  88. $tempFile = [System.IO.Path]::GetTempFileName() + ".reg"
  89. try {
  90. $process = Start-Process -FilePath "reg.exe" -ArgumentList @("export", $keyPath, $tempFile, "/y") -Wait -PassThru -NoNewWindow -RedirectStandardOutput $null -RedirectStandardError $null
  91. if ($process.ExitCode -eq 0 -and (Test-Path $tempFile)) {
  92. $keyContent = Get-Content -Path $tempFile -Encoding Unicode | Where-Object { $_ -notmatch "^Windows Registry Editor" -and $_ -ne "" }
  93. if ($keyContent) {
  94. $backupContent += ""
  95. $backupContent += "; === $keyName ==="
  96. $backupContent += $keyContent
  97. $backupCount++
  98. Write-Host "✓ Backed up: $keyName" -ForegroundColor $Colors.Success
  99. } else {
  100. Write-Host "→ Key exists but is empty: $keyName" -ForegroundColor $Colors.Gray
  101. }
  102. } else {
  103. Write-Host "→ Key not found (will be skipped): $keyName" -ForegroundColor $Colors.Gray
  104. }
  105. }
  106. finally {
  107. if (Test-Path $tempFile) {
  108. Remove-Item -Path $tempFile -Force -ErrorAction SilentlyContinue
  109. }
  110. }
  111. }
  112. # Save consolidated backup file
  113. if ($backupCount -gt 0) {
  114. $backupContent | Out-File -FilePath $BackupFile -Encoding Unicode -Force
  115. Write-Host "✓ Registry backup completed: $BackupFile" -ForegroundColor $Colors.Success
  116. Write-Host "→ Backed up $backupCount registry sections" -ForegroundColor $Colors.Info
  117. return $true
  118. } else {
  119. Write-Host "→ No registry keys found to backup" -ForegroundColor $Colors.Warning
  120. return $false
  121. }
  122. }
  123. catch {
  124. Write-Host "✗ Failed to create backup: $_" -ForegroundColor $Colors.Error
  125. return $false
  126. }
  127. }
  128. function Restore-RegistryBackup {
  129. <#
  130. .SYNOPSIS
  131. Restores registry from backup file
  132. .PARAMETER BackupFile
  133. Path to backup file to restore from
  134. #>
  135. param([string]$BackupFile)
  136. Write-Host "`n--- Restoring Registry Backup ---" -ForegroundColor $Colors.Section
  137. if (!(Test-Path $BackupFile)) {
  138. Write-Host "✗ Backup file not found: $BackupFile" -ForegroundColor $Colors.Error
  139. return $false
  140. }
  141. try {
  142. Write-Host "→ Validating backup file format..." -ForegroundColor $Colors.Info
  143. # Validate backup file
  144. $content = Get-Content -Path $BackupFile -TotalCount 5
  145. if ($content[0] -notmatch "Windows Registry Editor") {
  146. Write-Host "✗ Invalid backup file format" -ForegroundColor $Colors.Error
  147. return $false
  148. }
  149. Write-Host "→ Importing registry backup..." -ForegroundColor $Colors.Info
  150. $process = Start-Process -FilePath "reg.exe" -ArgumentList @("import", $BackupFile) -Wait -PassThru -NoNewWindow
  151. if ($process.ExitCode -eq 0) {
  152. Write-Host "✓ Registry restored successfully from: $BackupFile" -ForegroundColor $Colors.Success
  153. Write-Host "→ Restart may be required for changes to take effect" -ForegroundColor $Colors.Warning
  154. return $true
  155. } else {
  156. Write-Host "✗ Failed to restore registry (Exit code: $($process.ExitCode))" -ForegroundColor $Colors.Error
  157. return $false
  158. }
  159. }
  160. catch {
  161. Write-Host "✗ Error restoring backup: $_" -ForegroundColor $Colors.Error
  162. return $false
  163. }
  164. }
  165. # =======================================================
  166. # ENHANCED REGISTRY FUNCTIONS
  167. # =======================================================
  168. function Set-RegistryValue {
  169. param(
  170. [string]$Path,
  171. [string]$Name,
  172. [object]$Value,
  173. [Microsoft.Win32.RegistryValueKind]$Type = [Microsoft.Win32.RegistryValueKind]::DWord
  174. )
  175. try {
  176. if (!(Test-Path $Path)) {
  177. Write-Host "Registry path not found, skipping: $Path" -ForegroundColor $Colors.Gray
  178. return $false
  179. }
  180. $currentValue = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue
  181. if ($null -ne $currentValue -and $currentValue.$Name -eq $Value) {
  182. Write-Host "✓ $Name already set to $Value in $Path" -ForegroundColor $Colors.Success
  183. return $true
  184. }
  185. $null = Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop
  186. Write-Host "✓ Set $Name to $Value in $Path" -ForegroundColor $Colors.Success
  187. return $true
  188. }
  189. catch {
  190. Write-Host "✗ Failed to set $Name in $Path : $_" -ForegroundColor $Colors.Error
  191. return $false
  192. }
  193. }
  194. function Remove-TelemetryDirectory {
  195. param([string]$Path)
  196. if (Test-Path $Path) {
  197. try {
  198. $itemCount = (Get-ChildItem -Path $Path -Recurse -ErrorAction SilentlyContinue | Measure-Object).Count
  199. if ($itemCount -gt 0) {
  200. Remove-Item -Path $Path -Recurse -Force -Verbose:$false -ErrorAction Stop
  201. Write-Host "✓ Removed telemetry directory: $Path ($itemCount items)" -ForegroundColor $Colors.Success
  202. } else {
  203. Write-Host "→ Telemetry directory already empty: $Path" -ForegroundColor $Colors.Info
  204. }
  205. }
  206. catch {
  207. Write-Host "✗ Failed to remove: $Path - $_" -ForegroundColor $Colors.Error
  208. }
  209. } else {
  210. Write-Host "→ Telemetry directory not found: $Path" -ForegroundColor $Colors.Gray
  211. }
  212. }
  213. function Set-EnvironmentVariableIfNeeded {
  214. param(
  215. [string]$Name,
  216. [string]$Value,
  217. [string]$Target = 'User'
  218. )
  219. try {
  220. $currentValue = [Environment]::GetEnvironmentVariable($Name, $Target)
  221. if ($currentValue -eq $Value) {
  222. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  223. Write-Host "$Name " -NoNewline -ForegroundColor $Colors.Info
  224. Write-Host "already set to " -NoNewline -ForegroundColor $Colors.White
  225. Write-Host "$Value" -ForegroundColor $Colors.Success
  226. } else {
  227. [Environment]::SetEnvironmentVariable($Name, $Value, $Target)
  228. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  229. Write-Host "Set " -NoNewline -ForegroundColor $Colors.White
  230. Write-Host "$Name " -NoNewline -ForegroundColor $Colors.Info
  231. Write-Host "to " -NoNewline -ForegroundColor $Colors.White
  232. Write-Host "$Value" -ForegroundColor $Colors.Success
  233. }
  234. return $true
  235. }
  236. catch {
  237. Write-Host "✗ Failed to set environment variable $Name : $_" -ForegroundColor $Colors.Error
  238. return $false
  239. }
  240. }
  241. # =======================================================
  242. # MAIN SCRIPT LOGIC - HANDLE BACKUP/RESTORE OPERATIONS
  243. # =======================================================
  244. # Handle restore operation first
  245. if ($RestoreBackup) {
  246. $restored = Restore-RegistryBackup -BackupFile $BackupPath
  247. if ($restored) {
  248. Write-Host "`n✓ Restore operation completed successfully!" -ForegroundColor $Colors.Success
  249. Write-Host "→ Your telemetry settings have been restored from backup" -ForegroundColor $Colors.Info
  250. } else {
  251. Write-Host "`n✗ Restore operation failed!" -ForegroundColor $Colors.Error
  252. }
  253. Write-Host "`nPress Enter to exit..." -ForegroundColor $Colors.White
  254. Read-Host
  255. exit
  256. }
  257. # Handle backup creation
  258. if ($CreateBackup) {
  259. $backupCreated = New-RegistryBackup -BackupFile $BackupPath
  260. if ($backupCreated) {
  261. Write-Host "`n✓ Backup created successfully at: $BackupPath" -ForegroundColor $Colors.Success
  262. Write-Host "→ You can restore with: .\off_telemetry_ps7.ps1 -RestoreBackup -BackupPath '$BackupPath'" -ForegroundColor $Colors.Info
  263. } else {
  264. Write-Host "`n→ Backup creation completed (no existing telemetry settings found)" -ForegroundColor $Colors.Warning
  265. }
  266. Write-Host "`nOptions:" -ForegroundColor $Colors.White
  267. Write-Host "1. Continue with telemetry disable (recommended)" -ForegroundColor $Colors.Info
  268. Write-Host "2. Exit and run backup restore later" -ForegroundColor $Colors.Info
  269. $choice = Read-Host "`nContinue with telemetry disable? (y/n)"
  270. if ($choice -ne 'y' -and $choice -ne 'Y' -and $choice -ne '1') {
  271. Write-Host "Exiting. Run the script again without -CreateBackup to disable telemetry." -ForegroundColor $Colors.Info
  272. exit
  273. }
  274. Write-Host ""
  275. }
  276. # =======================================================
  277. # VISUAL STUDIO VERSIONS DETECTION AND PROCESSING
  278. # =======================================================
  279. Write-Host "--- Checking and Disabling Visual Studio Telemetry (Existing Paths Only) ---" -ForegroundColor $Colors.Section
  280. # Visual Studio versions to check
  281. $vsVersions = @{
  282. "14.0" = "Visual Studio 2015"
  283. "15.0" = "Visual Studio 2017"
  284. "16.0" = "Visual Studio 2019"
  285. "17.0" = "Visual Studio 2022"
  286. }
  287. # Track which versions are actually installed
  288. $installedVersions = @()
  289. foreach ($version in $vsVersions.Keys) {
  290. $vsName = $vsVersions[$version]
  291. Write-Host "`n--- Checking $vsName (version $version) ---" -ForegroundColor $Colors.Info
  292. $foundVersion = $false
  293. # Check 64-bit paths
  294. if ([Environment]::Is64BitOperatingSystem) {
  295. $path64 = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\VSCommon\$version\SQM"
  296. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  297. Write-Host "Checking 64-bit path for " -NoNewline -ForegroundColor $Colors.White
  298. Write-Host "$vsName" -ForegroundColor $Colors.Info
  299. $result64 = Set-RegistryValue -Path $path64 -Name "OptIn" -Value 0
  300. if ($result64) {
  301. $foundVersion = $true
  302. }
  303. }
  304. # Check 32-bit paths
  305. $path32 = "HKLM:\SOFTWARE\Microsoft\VSCommon\$version\SQM"
  306. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  307. Write-Host "Checking 32-bit path for " -NoNewline -ForegroundColor $Colors.White
  308. Write-Host "$vsName" -ForegroundColor $Colors.Info
  309. $result32 = Set-RegistryValue -Path $path32 -Name "OptIn" -Value 0
  310. if ($result32) {
  311. $foundVersion = $true
  312. }
  313. # Track if this version was found
  314. if ($foundVersion) {
  315. $installedVersions += $version
  316. Write-Host "✓ Found $vsName installation" -ForegroundColor $Colors.Success
  317. }
  318. }
  319. # =======================================================
  320. # VISUAL STUDIO POLICY SETTINGS (Only if they exist)
  321. # =======================================================
  322. Write-Host "`n--- Checking Visual Studio Policy Settings ---" -ForegroundColor $Colors.Section
  323. # Base policy paths
  324. $policyBase = "HKLM:\SOFTWARE\Policies\Microsoft\VisualStudio"
  325. $feedbackPath = "$policyBase\Feedback"
  326. $sqmPath = "$policyBase\SQM"
  327. $telemetryPath = "HKCU:\Software\Microsoft\VisualStudio\Telemetry"
  328. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  329. Write-Host "Checking Visual Studio Policy paths..." -ForegroundColor $Colors.White
  330. # Feedback settings
  331. Set-RegistryValue -Path $feedbackPath -Name "DisableFeedbackDialog" -Value 1
  332. Set-RegistryValue -Path $feedbackPath -Name "DisableEmailInput" -Value 1
  333. Set-RegistryValue -Path $feedbackPath -Name "DisableScreenshotCapture" -Value 1
  334. # SQM and telemetry settings
  335. Set-RegistryValue -Path $sqmPath -Name "OptIn" -Value 0
  336. Set-RegistryValue -Path $telemetryPath -Name "TurnOffSwitch" -Value 1
  337. # =======================================================
  338. # ADDITIONAL VISUAL STUDIO REGISTRY PATHS
  339. # =======================================================
  340. Write-Host "`n--- Checking Additional Visual Studio Registry Paths ---" -ForegroundColor $Colors.Section
  341. # Additional paths that might exist
  342. $additionalPaths = @(
  343. "HKCU:\Software\Microsoft\VisualStudio\14.0\General",
  344. "HKCU:\Software\Microsoft\VisualStudio\15.0\General",
  345. "HKCU:\Software\Microsoft\VisualStudio\16.0\General",
  346. "HKCU:\Software\Microsoft\VisualStudio\17.0\General"
  347. )
  348. foreach ($path in $additionalPaths) {
  349. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  350. Write-Host "Checking additional path..." -ForegroundColor $Colors.White
  351. Set-RegistryValue -Path $path -Name "EnableSQM" -Value 0
  352. }
  353. # Check Experience Improvement Program paths
  354. $experiencePaths = @(
  355. "HKLM:\SOFTWARE\Microsoft\SQMClient",
  356. "HKLM:\SOFTWARE\Wow6432Node\Microsoft\SQMClient"
  357. )
  358. foreach ($path in $experiencePaths) {
  359. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  360. Write-Host "Checking SQM Client path..." -ForegroundColor $Colors.White
  361. Set-RegistryValue -Path $path -Name "CEIPEnable" -Value 0
  362. }
  363. # =======================================================
  364. # TELEMETRY DIRECTORIES CLEANUP
  365. # =======================================================
  366. Write-Host "`n--- Checking Telemetry Directories ---" -ForegroundColor $Colors.Section
  367. $telemetryDirs = @(
  368. "$env:APPDATA\vstelemetry",
  369. "$env:LOCALAPPDATA\Microsoft\VSApplicationInsights",
  370. "$env:PROGRAMDATA\Microsoft\VSApplicationInsights",
  371. "$env:TEMP\Microsoft\VSApplicationInsights",
  372. "$env:TEMP\VSFaultInfo",
  373. "$env:TEMP\VSFeedbackIntelliCodeLogs",
  374. "$env:TEMP\VSFeedbackPerfWatsonData",
  375. "$env:TEMP\VSFeedbackVSRTCLogs",
  376. "$env:TEMP\VSRemoteControl",
  377. "$env:TEMP\VSTelem",
  378. "$env:TEMP\VSTelem.Out"
  379. )
  380. foreach ($dir in $telemetryDirs) {
  381. Remove-TelemetryDirectory -Path $dir
  382. }
  383. # =======================================================
  384. # .NET AND NUGET TELEMETRY DISABLE
  385. # =======================================================
  386. Write-Host "`n--- Disabling .NET and NuGet Telemetry ---" -ForegroundColor $Colors.Section
  387. # Check and set .NET CLI telemetry
  388. Set-EnvironmentVariableIfNeeded -Name 'DOTNET_CLI_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  389. # Check and set NuGet telemetry
  390. Set-EnvironmentVariableIfNeeded -Name 'NUGET_TELEMETRY_OPTOUT' -Value 'true' -Target 'User'
  391. # =======================================================
  392. # VISUAL STUDIO STANDARD COLLECTOR SERVICE
  393. # =======================================================
  394. Write-Host "`n--- Managing VS Standard Collector Service ---" -ForegroundColor $Colors.Section
  395. $serviceName = 'VSStandardCollectorService150'
  396. $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
  397. if ($service) {
  398. Write-Host "→ Found service: $serviceName" -ForegroundColor $Colors.Info
  399. # Check and stop service if running
  400. if ($service.Status -eq 'Running') {
  401. try {
  402. Stop-Service -Name $serviceName -Force -ErrorAction Stop
  403. Write-Host "✓ Stopped $serviceName" -ForegroundColor $Colors.Success
  404. }
  405. catch {
  406. Write-Host "✗ Could not stop $serviceName : $_" -ForegroundColor $Colors.Error
  407. }
  408. } else {
  409. Write-Host "→ Service $serviceName is already stopped (Status: $($service.Status))" -ForegroundColor $Colors.Info
  410. }
  411. # Check and disable service
  412. if ($service.StartType -eq 'Disabled') {
  413. Write-Host "✓ $serviceName already disabled" -ForegroundColor $Colors.Success
  414. } else {
  415. try {
  416. Set-Service -Name $serviceName -StartupType Disabled -Confirm:$false -ErrorAction Stop
  417. Write-Host "✓ Disabled $serviceName" -ForegroundColor $Colors.Success
  418. }
  419. catch {
  420. Write-Host "✗ Could not disable $serviceName : $_" -ForegroundColor $Colors.Error
  421. }
  422. }
  423. } else {
  424. Write-Host "→ $serviceName not found (already removed or not installed)" -ForegroundColor $Colors.Gray
  425. }
  426. # =======================================================
  427. # VISUAL STUDIO CODE SETTINGS
  428. # =======================================================
  429. Write-Host "`n--- Configuring Visual Studio Code Settings ---" -ForegroundColor $Colors.Section
  430. $vscodeSettings = "$env:APPDATA\Code\User\settings.json"
  431. $vscodeUserDir = "$env:APPDATA\Code\User"
  432. $vscodeDetected = $false
  433. if (!(Test-Path "$env:APPDATA\Code")) {
  434. Write-Host "→ Visual Studio Code not detected" -ForegroundColor $Colors.Gray
  435. } else {
  436. Write-Host "→ Visual Studio Code detected" -ForegroundColor $Colors.Info
  437. $vscodeDetected = $true
  438. # Create User directory if needed
  439. if (!(Test-Path $vscodeUserDir)) {
  440. try {
  441. $null = New-Item -Path $vscodeUserDir -ItemType Directory -Force
  442. Write-Host "→ Created VS Code User directory" -ForegroundColor $Colors.Info
  443. } catch {
  444. Write-Host "✗ Failed to create VS Code User directory: $_" -ForegroundColor $Colors.Error
  445. }
  446. }
  447. # Privacy settings
  448. $privacyConfig = @{
  449. "telemetry.enableTelemetry" = $false
  450. "telemetry.enableCrashReporter" = $false
  451. "workbench.enableExperiments" = $false
  452. "update.mode" = "manual"
  453. "update.showReleaseNotes" = $false
  454. "extensions.autoCheckUpdates" = $false
  455. "extensions.showRecommendationsOnlyOnDemand" = $true
  456. "git.autofetch" = $false
  457. "npm.fetchOnlinePackageInfo" = $false
  458. }
  459. try {
  460. # Load existing settings
  461. $settings = @{}
  462. if (Test-Path $vscodeSettings) {
  463. $content = Get-Content $vscodeSettings -Raw -ErrorAction SilentlyContinue
  464. if ($content -and $content.Trim()) {
  465. try {
  466. # Use PowerShell's built-in JSON cmdlets
  467. $settingsObj = $content | ConvertFrom-Json
  468. # Convert PSCustomObject to hashtable for easier manipulation
  469. $settings = @{}
  470. $settingsObj.PSObject.Properties | ForEach-Object {
  471. $settings[$_.Name] = $_.Value
  472. }
  473. Write-Host "→ Found existing VS Code settings file" -ForegroundColor $Colors.Info
  474. }
  475. catch {
  476. Write-Host "→ Could not parse existing settings, creating new ones" -ForegroundColor $Colors.Warning
  477. $settings = @{}
  478. }
  479. }
  480. }
  481. # Update settings
  482. $changesMade = $false
  483. foreach ($key in $privacyConfig.Keys) {
  484. $value = $privacyConfig[$key]
  485. if ($settings.ContainsKey($key) -and $settings[$key] -eq $value) {
  486. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  487. Write-Host "$key " -NoNewline -ForegroundColor $Colors.Info
  488. Write-Host "already set to " -NoNewline -ForegroundColor $Colors.White
  489. Write-Host "$value" -ForegroundColor $Colors.Success
  490. } else {
  491. $settings[$key] = $value
  492. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  493. Write-Host "Updated " -NoNewline -ForegroundColor $Colors.White
  494. Write-Host "$key " -NoNewline -ForegroundColor $Colors.Info
  495. Write-Host "to " -NoNewline -ForegroundColor $Colors.White
  496. Write-Host "$value" -ForegroundColor $Colors.Success
  497. $changesMade = $true
  498. }
  499. }
  500. # Save settings if changes were made
  501. if ($changesMade -or !(Test-Path $vscodeSettings)) {
  502. $json = $settings | ConvertTo-Json -Depth 10
  503. $json | Out-File -FilePath $vscodeSettings -Encoding UTF8
  504. Write-Host "✓ Saved VS Code privacy settings" -ForegroundColor $Colors.Success
  505. } else {
  506. Write-Host "→ No changes needed for VS Code settings" -ForegroundColor $Colors.Info
  507. }
  508. }
  509. catch {
  510. Write-Host "✗ Failed to update VS Code settings: $_" -ForegroundColor $Colors.Error
  511. }
  512. }
  513. # =======================================================
  514. # ADDITIONAL POWERSHELL 7 SPECIFIC CHECKS
  515. # =======================================================
  516. Write-Host "`n--- PowerShell 7 Specific Checks ---" -ForegroundColor $Colors.Section
  517. # Check if PowerShell telemetry is disabled
  518. try {
  519. $psDataCollection = [Microsoft.PowerShell.Telemetry.ApplicationInsightsTelemetry]::Enabled -eq $false
  520. if ($psDataCollection) {
  521. Write-Host "✓ PowerShell telemetry already disabled" -ForegroundColor $Colors.Success
  522. } else {
  523. Write-Host "→ PowerShell telemetry status:" -ForegroundColor $Colors.Info
  524. }
  525. } catch {
  526. Write-Host "→ Could not check PowerShell telemetry status" -ForegroundColor $Colors.Gray
  527. }
  528. # Check PowerShell environment variables
  529. Set-EnvironmentVariableIfNeeded -Name 'POWERSHELL_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  530. # =======================================================
  531. # SUMMARY
  532. # =======================================================
  533. Write-Host "`n========================================" -ForegroundColor $Colors.Title
  534. Write-Host "TELEMETRY DISABLE COMPLETE" -ForegroundColor $Colors.Title
  535. Write-Host "========================================" -ForegroundColor $Colors.Title
  536. Write-Host "`nProcessed telemetry settings for:" -ForegroundColor $Colors.White
  537. # Visual Studio versions with status colors
  538. if ($installedVersions.Count -gt 0) {
  539. foreach ($version in $installedVersions) {
  540. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  541. Write-Host "$($vsVersions[$version]) " -NoNewline -ForegroundColor $Colors.Info
  542. Write-Host "(detected and processed)" -ForegroundColor $Colors.Success
  543. }
  544. } else {
  545. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Gray
  546. Write-Host "No Visual Studio versions detected" -ForegroundColor $Colors.Gray
  547. }
  548. # Visual Studio Code with status colors
  549. if ($vscodeDetected) {
  550. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  551. Write-Host "Visual Studio Code " -NoNewline -ForegroundColor $Colors.Info
  552. Write-Host "(detected and configured)" -ForegroundColor $Colors.Success
  553. } else {
  554. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Gray
  555. Write-Host "Visual Studio Code " -NoNewline -ForegroundColor $Colors.Info
  556. Write-Host "(not found)" -ForegroundColor $Colors.Gray
  557. }
  558. # .NET CLI status
  559. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  560. Write-Host ".NET CLI " -NoNewline -ForegroundColor $Colors.Info
  561. Write-Host "(telemetry disabled)" -ForegroundColor $Colors.Success
  562. # NuGet status
  563. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  564. Write-Host "NuGet " -NoNewline -ForegroundColor $Colors.Info
  565. Write-Host "(telemetry disabled)" -ForegroundColor $Colors.Success
  566. # VS Standard Collector Service status
  567. if ($null -ne $service) {
  568. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  569. Write-Host "VS Standard Collector Service " -NoNewline -ForegroundColor $Colors.Info
  570. Write-Host "(processed)" -ForegroundColor $Colors.Success
  571. } else {
  572. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Gray
  573. Write-Host "VS Standard Collector Service " -NoNewline -ForegroundColor $Colors.Info
  574. Write-Host "(not found)" -ForegroundColor $Colors.Gray
  575. }
  576. # PowerShell 7 status
  577. $psTelemetryOptOut = [Environment]::GetEnvironmentVariable('POWERSHELL_TELEMETRY_OPTOUT', 'User')
  578. if ($psTelemetryOptOut -eq '1') {
  579. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  580. Write-Host "PowerShell 7 telemetry " -NoNewline -ForegroundColor $Colors.Info
  581. Write-Host "(opt-out configured via environment variable)" -ForegroundColor $Colors.Success
  582. } else {
  583. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Gray
  584. Write-Host "PowerShell 7 telemetry " -NoNewline -ForegroundColor $Colors.Info
  585. Write-Host "(opt-out not configured; current value: $($psTelemetryOptOut ?? 'not set'))" -ForegroundColor $Colors.Gray
  586. }
  587. # Customer Experience Improvement Program status
  588. $experienceDisabled = $true
  589. foreach ($path in $experiencePaths) {
  590. $value = Get-ItemProperty -Path $path -Name "CEIPEnable" -ErrorAction SilentlyContinue
  591. if ($value -and $value.CEIPEnable -ne 0) {
  592. $experienceDisabled = $false
  593. break
  594. }
  595. }
  596. if ($experienceDisabled) {
  597. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  598. Write-Host "Customer Experience Improvement Program " -NoNewline -ForegroundColor $Colors.Info
  599. Write-Host "(disabled)" -ForegroundColor $Colors.Success
  600. } else {
  601. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Gray
  602. Write-Host "Customer Experience Improvement Program " -NoNewline -ForegroundColor $Colors.Info
  603. Write-Host "(not fully disabled)" -ForegroundColor $Colors.Gray
  604. }
  605. # Telemetry Directories Cleanup status
  606. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success
  607. Write-Host "Telemetry Directories Cleanup " -NoNewline -ForegroundColor $Colors.Info
  608. Write-Host "(processed)" -ForegroundColor $Colors.Success
  609. # =======================================================
  610. # ADDITIONAL FEATURES AND ENVIRONMENT VARIABLES
  611. # =======================================================
  612. Write-Host "`n--- Optional: Additional Features and Environment Variables ---" -ForegroundColor $Colors.Section
  613. Write-Host "This will perform additional configuration:" -ForegroundColor $Colors.Info
  614. Write-Host "• Disable Visual Studio Settings Synchronization" -ForegroundColor $Colors.Info
  615. Write-Host "• Disable Live Share" -ForegroundColor $Colors.Info
  616. Write-Host "• Disable IntelliCode" -ForegroundColor $Colors.Info
  617. Write-Host "• Disable CodeLens" -ForegroundColor $Colors.Info
  618. Write-Host "• Set additional environment variables (INTELLICODE_TELEMETRY_OPTOUT, LIVESHARE_TELEMETRY_OPTOUT, VSSDK_TELEMETRY_OPTOUT)" -ForegroundColor $Colors.Info
  619. $enableAdditional = Read-Host "`nEnable additional configuration? (y/n)"
  620. if ($enableAdditional -eq 'y' -or $enableAdditional -eq 'Y' -or $enableAdditional -eq 'yes' -or $enableAdditional -eq 'Yes' -or $enableAdditional -eq 'YES') {
  621. # =======================================================
  622. # VISUAL STUDIO ADDITIONAL FEATURES DISABLE
  623. # =======================================================
  624. Write-Host "`n--- Disabling Additional Visual Studio Features ---" -ForegroundColor $Colors.Section
  625. if ($installedVersions.Count -gt 0) {
  626. foreach ($version in $installedVersions) {
  627. $vsName = $vsVersions[$version]
  628. Write-Host "`n--- Processing Additional Features for $vsName (version $version) ---" -ForegroundColor $Colors.Info
  629. # =======================================================
  630. # SETTINGS SYNCHRONIZATION
  631. # =======================================================
  632. Write-Host "→ Disabling Settings Synchronization..." -ForegroundColor $Colors.Info
  633. $settingsPaths = @(
  634. "HKCU:\Software\Microsoft\VisualStudio\$version\Settings",
  635. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\Settings"
  636. )
  637. foreach ($path in $settingsPaths) {
  638. Set-RegistryValue -Path $path -Name "SyncSettings" -Value 0
  639. Set-RegistryValue -Path $path -Name "EnableRoaming" -Value 0
  640. Set-RegistryValue -Path $path -Name "EnableSync" -Value 0
  641. Set-RegistryValue -Path $path -Name "DisableSync" -Value 1
  642. }
  643. # Additional settings sync paths
  644. $syncPath = "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\ConnectedServices"
  645. Set-RegistryValue -Path $syncPath -Name "Provider.Enabled" -Value 0
  646. # =======================================================
  647. # LIVE SHARE
  648. # =======================================================
  649. Write-Host "→ Disabling Live Share..." -ForegroundColor $Colors.Info
  650. $liveSharePaths = @(
  651. "HKCU:\Software\Microsoft\VisualStudio\$version\LiveShare",
  652. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\LiveShare"
  653. )
  654. foreach ($path in $liveSharePaths) {
  655. Set-RegistryValue -Path $path -Name "Enabled" -Value 0
  656. Set-RegistryValue -Path $path -Name "EnableTelemetry" -Value 0
  657. Set-RegistryValue -Path $path -Name "DisableTelemetry" -Value 1
  658. Set-RegistryValue -Path $path -Name "OptedIn" -Value 0
  659. }
  660. # Live Share telemetry
  661. $liveShareTelemetryPath = "HKCU:\Software\Microsoft\VisualStudio\$version\LiveShare\Telemetry"
  662. Set-RegistryValue -Path $liveShareTelemetryPath -Name "Enabled" -Value 0
  663. Set-RegistryValue -Path $liveShareTelemetryPath -Name "OptOut" -Value 1
  664. # =======================================================
  665. # INTELLICODE
  666. # =======================================================
  667. Write-Host "→ Disabling IntelliCode..." -ForegroundColor $Colors.Info
  668. $intelliCodePaths = @(
  669. "HKCU:\Software\Microsoft\VisualStudio\$version\IntelliCode",
  670. "HKCU:\Software\Microsoft\VisualStudio\$version\IntelliSense\IntelliCode",
  671. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\IntelliCode"
  672. )
  673. foreach ($path in $intelliCodePaths) {
  674. Set-RegistryValue -Path $path -Name "DisableTelemetry" -Value 1
  675. Set-RegistryValue -Path $path -Name "EnableTelemetry" -Value 0
  676. Set-RegistryValue -Path $path -Name "OptedIn" -Value 0
  677. Set-RegistryValue -Path $path -Name "Enabled" -Value 0
  678. Set-RegistryValue -Path $path -Name "ModelDownloadEnabled" -Value 0
  679. }
  680. # IntelliCode privacy settings
  681. $intelliCodePrivacyPath = "HKCU:\Software\Microsoft\VisualStudio\$version\IntelliCode\Privacy"
  682. Set-RegistryValue -Path $intelliCodePrivacyPath -Name "TelemetryOptOut" -Value 1
  683. Set-RegistryValue -Path $intelliCodePrivacyPath -Name "DataCollection" -Value 0
  684. Set-RegistryValue -Path $intelliCodePrivacyPath -Name "UsageDataOptOut" -Value 1
  685. # =======================================================
  686. # CODELENS
  687. # =======================================================
  688. Write-Host "→ Disabling CodeLens..." -ForegroundColor $Colors.Info
  689. $codeLensPaths = @(
  690. "HKCU:\Software\Microsoft\VisualStudio\$version\CodeLens",
  691. "HKCU:\Software\Microsoft\VisualStudio\$version\TextEditor\CodeLens",
  692. "HKCU:\Software\Microsoft\VisualStudio\$version\ApplicationPrivateSettings\Microsoft\VisualStudio\CodeLens"
  693. )
  694. foreach ($path in $codeLensPaths) {
  695. Set-RegistryValue -Path $path -Name "Disabled" -Value 1
  696. Set-RegistryValue -Path $path -Name "ShowAuthorCodeLens" -Value 0
  697. Set-RegistryValue -Path $path -Name "ShowReferencesCodeLens" -Value 0
  698. Set-RegistryValue -Path $path -Name "ShowTestCodeLens" -Value 0
  699. Set-RegistryValue -Path $path -Name "Enabled" -Value 0
  700. }
  701. # CodeLens telemetry
  702. $codeLensTelemetryPath = "HKCU:\Software\Microsoft\VisualStudio\$version\CodeLens\Telemetry"
  703. Set-RegistryValue -Path $codeLensTelemetryPath -Name "Enabled" -Value 0
  704. Set-RegistryValue -Path $codeLensTelemetryPath -Name "OptOut" -Value 1
  705. }
  706. } else {
  707. Write-Host "→ No Visual Studio installations detected, skipping additional features" -ForegroundColor $Colors.Gray
  708. }
  709. # =======================================================
  710. # ADDITIONAL ENVIRONMENT VARIABLES
  711. # =======================================================
  712. Write-Host "`n--- Setting Additional Environment Variables ---" -ForegroundColor $Colors.Section
  713. Set-EnvironmentVariableIfNeeded -Name 'INTELLICODE_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  714. Set-EnvironmentVariableIfNeeded -Name 'LIVESHARE_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  715. Set-EnvironmentVariableIfNeeded -Name 'VSSDK_TELEMETRY_OPTOUT' -Value '1' -Target 'User'
  716. Write-Host "`n✓ Additional configuration completed" -ForegroundColor $Colors.Success
  717. } else {
  718. Write-Host "→ Skipping additional configuration" -ForegroundColor $Colors.Info
  719. }
  720. Write-Host "`nLegend:" -ForegroundColor $Colors.White
  721. Write-Host "✓ " -NoNewline -ForegroundColor $Colors.Success; Write-Host "Action completed successfully" -ForegroundColor $Colors.Gray
  722. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info; Write-Host "Information or preparatory action" -ForegroundColor $Colors.Gray
  723. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Gray; Write-Host "Component not found or not processed" -ForegroundColor $Colors.Gray
  724. Write-Host "✗ " -NoNewline -ForegroundColor $Colors.Error; Write-Host "Error occurred" -ForegroundColor $Colors.Gray
  725. Write-Host "`nUsage Examples:" -ForegroundColor $Colors.White
  726. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  727. Write-Host "Create backup first: " -NoNewline -ForegroundColor $Colors.White
  728. Write-Host ".\off_telemetry_ps7.ps1 -CreateBackup" -ForegroundColor $Colors.Info
  729. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  730. Write-Host "Restore from backup: " -NoNewline -ForegroundColor $Colors.White
  731. Write-Host ".\off_telemetry_ps7.ps1 -RestoreBackup -BackupPath 'path\to\backup.reg'" -ForegroundColor $Colors.Info
  732. Write-Host "→ " -NoNewline -ForegroundColor $Colors.Info
  733. Write-Host "Run without backup: " -NoNewline -ForegroundColor $Colors.White
  734. Write-Host ".\off_telemetry_ps7.ps1" -ForegroundColor $Colors.Info
  735. if (!$CreateBackup) {
  736. Write-Host "`n⚠ " -NoNewline -ForegroundColor $Colors.Warning
  737. Write-Host "Tip: Run with -CreateBackup parameter to create registry backup first" -ForegroundColor $Colors.Warning
  738. }
  739. Write-Host "`n⚠ " -NoNewline -ForegroundColor $Colors.Warning
  740. Write-Host "Restart may be required for all changes to take effect." -ForegroundColor $Colors.Warning
  741. Write-Host "`nPress Enter to exit..." -ForegroundColor $Colors.White
  742. $null = Read-Host