Public/Disable-CopilotAIFeature.ps1
|
function Disable-CopilotAIFeature { <# .SYNOPSIS Disables specific Windows AI features on Copilot+ PCs. .DESCRIPTION Configures registry policies, stops services, and disables scheduled tasks for specified Windows AI features. Supports targeting individual features or all features at once. Features: - Recall: Disables Windows Recall (snapshots, AI data analysis) - ClickToDo: Disables Click to Do visual assistant - WindowsAI: Disables the Windows AI Fabric Service (WSAIFabricSvc) - All: Disables all of the above All changes are reversible via Enable-CopilotAIFeature. .PARAMETER Feature One or more features to disable. Accepts multiple values. .EXAMPLE Disable-CopilotAIFeature -Feature Recall Disable only Windows Recall. .EXAMPLE Disable-CopilotAIFeature -Feature All -WhatIf Preview all changes that would be made to disable every AI feature. .EXAMPLE Disable-CopilotAIFeature -Feature Recall, ClickToDo Disable Recall and Click to Do but leave the AI Fabric Service running. .LINK https://github.com/DailenG/WinslopFix #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param( [Parameter(Mandatory)] [ValidateSet('Recall', 'ClickToDo', 'WindowsAI', 'All')] [string[]]$Feature ) process { Assert-Administrator # Expand 'All' into individual features if ('All' -in $Feature) { $Feature = @('Recall', 'ClickToDo', 'WindowsAI') } $results = [System.Collections.Generic.List[PSCustomObject]]::new() # --- Recall --- if ('Recall' -in $Feature) { $regPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI' if ($PSCmdlet.ShouldProcess('Windows Recall', 'Disable via registry policies')) { if (-not (Test-Path -LiteralPath $regPath)) { New-Item -Path $regPath -Force | Out-Null } Set-ItemProperty -Path $regPath -Name 'DisableAIDataAnalysis' -Value 1 -Type DWord -Force Set-ItemProperty -Path $regPath -Name 'DisableRecall' -Value 1 -Type DWord -Force Set-ItemProperty -Path $regPath -Name 'AllowRecallEnablement' -Value 0 -Type DWord -Force Write-Verbose 'Recall disabled via registry policies.' } # Disable Recall-related service if ($PSCmdlet.ShouldProcess('ScreenshotIndexerService', 'Stop and disable service')) { $svc = Get-Service -Name 'ScreenshotIndexerService' -ErrorAction SilentlyContinue if ($svc) { Stop-Service -Name 'ScreenshotIndexerService' -Force -ErrorAction SilentlyContinue Set-Service -Name 'ScreenshotIndexerService' -StartupType Disabled -ErrorAction SilentlyContinue Write-Verbose 'ScreenshotIndexerService stopped and disabled.' } else { Write-Verbose 'ScreenshotIndexerService not found (may not exist on this build).' } } # Disable Recall-related scheduled tasks if ($PSCmdlet.ShouldProcess('Recall Scheduled Tasks', 'Disable AI snapshot tasks')) { $recallTasks = Get-ScheduledTask -TaskPath '\Microsoft\Windows\WindowsAI\' -ErrorAction SilentlyContinue | Where-Object { $_.TaskName -match 'Recall|Snapshot|ScreenshotIndex' } foreach ($task in $recallTasks) { Disable-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue | Out-Null Write-Verbose "Disabled scheduled task: $($task.TaskName)" } } Write-WinslopFixLog -Message 'Windows Recall disabled (registry, service, tasks).' -EventId 4000 $results.Add([PSCustomObject]@{ Feature = 'Recall' Action = 'Disabled' Details = 'Registry policies set, ScreenshotIndexerService disabled, scheduled tasks disabled' }) } # --- Click to Do --- if ('ClickToDo' -in $Feature) { $regPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI' if ($PSCmdlet.ShouldProcess('Click to Do', 'Disable via registry policy')) { if (-not (Test-Path -LiteralPath $regPath)) { New-Item -Path $regPath -Force | Out-Null } Set-ItemProperty -Path $regPath -Name 'DisableClickToDo' -Value 1 -Type DWord -Force Write-Verbose 'Click to Do disabled via registry policy.' } Write-WinslopFixLog -Message 'Click to Do disabled via registry policy.' -EventId 4000 $results.Add([PSCustomObject]@{ Feature = 'ClickToDo' Action = 'Disabled' Details = 'Registry policy set: DisableClickToDo = 1' }) } # --- Windows AI Fabric Service --- if ('WindowsAI' -in $Feature) { if ($PSCmdlet.ShouldProcess('WSAIFabricSvc', 'Stop and disable Windows AI Fabric Service')) { $svc = Get-Service -Name 'WSAIFabricSvc' -ErrorAction SilentlyContinue if ($svc) { Stop-Service -Name 'WSAIFabricSvc' -Force -ErrorAction SilentlyContinue Set-Service -Name 'WSAIFabricSvc' -StartupType Disabled -ErrorAction SilentlyContinue Write-Verbose 'WSAIFabricSvc stopped and disabled.' } else { Write-Verbose 'WSAIFabricSvc not found (may not exist on this build).' } } # Disable all Windows AI scheduled tasks if ($PSCmdlet.ShouldProcess('Windows AI Scheduled Tasks', 'Disable all AI tasks')) { $aiTasks = Get-ScheduledTask -TaskPath '\Microsoft\Windows\WindowsAI\' -ErrorAction SilentlyContinue foreach ($task in $aiTasks) { Disable-ScheduledTask -InputObject $task -ErrorAction SilentlyContinue | Out-Null Write-Verbose "Disabled scheduled task: $($task.TaskName)" } } Write-WinslopFixLog -Message 'Windows AI Fabric Service disabled (service, scheduled tasks).' -EventId 4000 $results.Add([PSCustomObject]@{ Feature = 'WindowsAI' Action = 'Disabled' Details = 'WSAIFabricSvc disabled, all WindowsAI scheduled tasks disabled' }) } return $results } } |