Skip to content

Commit 9e89959

Browse files
authored
Merge pull request #35 from carterscode/fix/search-ai-suggestions-popup
fix(ai): stop recurring Search-box-AI drift popup with reliable Win11 keys
2 parents 2fc52b6 + 88f0466 commit 9e89959

5 files changed

Lines changed: 138 additions & 48 deletions

File tree

docs/SETTINGS-REFERENCE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ Every setting here is managed via the Settings window. Toggle **Monitor** to hav
524524

525525
`ai.settingssearch`   **Recommended:** Off
526526

527-
**What it does.** Two HKCU policies: DisableSearchBoxSuggestions (kills the AI/Copilot-flavored web suggestion layer in the Windows search box) and TaskbarCompanion (the floating Copilot widget Windows can dock next to the taskbar). HKCU only -- no UAC.
527+
**What it does.** Three HKCU values: BingSearchEnabled=0 (the value Windows 11 actually honors for the AI/web suggestion layer in the search box -- this is the authoritative one), IsDynamicSearchBoxEnabled=0 (search highlights / the companion content), and the legacy DisableSearchBoxSuggestions=1 policy (best-effort -- unreliable on Win11). HKCU only -- no UAC.
528528

529529
**Why you'd change it.** The search box's AI suggestion layer calls Microsoft web endpoints to suggest answers as you type. The taskbar companion is a floating overlay some Windows 11 builds enable by default. Both are noise for users who use the search box for files and apps.
530530

@@ -540,7 +540,7 @@ Every setting here is managed via the Settings window. Toggle **Monitor** to hav
540540

541541
**Risks.** You lose the web-suggestion layer and the taskbar companion. Search itself works exactly as before.
542542

543-
**Reversible via.** Delete DisableSearchBoxSuggestions from HKCU\SOFTWARE\Policies\Microsoft\Windows\Explorer and TaskbarCompanion from HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced.
543+
**Reversible via.** Delete BingSearchEnabled from HKCU\Software\Microsoft\Windows\CurrentVersion\Search, IsDynamicSearchBoxEnabled from HKCU\Software\Microsoft\Windows\CurrentVersion\SearchSettings, and DisableSearchBoxSuggestions from HKCU\SOFTWARE\Policies\Microsoft\Windows\Explorer (or set them back to 1 / 1 / absent).
544544

545545

546546
### Typing / input insights data collection

src/GamerGuardian/Monitors/SettingsSearchAiMonitor.cs

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,50 @@
44
namespace GamerGuardian.Monitors;
55

66
/// <summary>
7-
/// Disables Copilot-flavored search suggestions in the Windows Search box
8-
/// + the taskbar "companion" widget. Both are HKCU policies -- no UAC.
7+
/// Disables the web/Copilot-flavored suggestion layer in the Windows Search box
8+
/// plus the "search highlights" companion content. All HKCU -- no UAC.
99
///
10-
/// <para>Note: this does NOT disable the Windows Search index itself. Start
11-
/// menu search, Explorer search, and Outlook search continue to work; only
12-
/// the AI-flavored web/Copilot suggestion layer is silenced.</para>
10+
/// <para><b>Why the mechanism changed (v0.1.41).</b> The original implementation
11+
/// keyed both the write and the drift signal on
12+
/// <c>HKCU\SOFTWARE\Policies\Microsoft\Windows\Explorer\DisableSearchBoxSuggestions</c>
13+
/// plus a non-existent <c>TaskbarCompanion</c> Advanced value. On most Windows 11
14+
/// builds neither is reliable: the Explorer policy frequently doesn't take effect
15+
/// (and on managed/MDM machines the Policies hive can be locked, so the write
16+
/// throws and is swallowed), and <c>TaskbarCompanion</c> is not a real value name
17+
/// so it never persists. When the written value doesn't read back, the apply+verify
18+
/// pass keeps reporting drift -> MonitorService backs the setting off for 15 min ->
19+
/// the drift item gets promoted to the notification queue -> the drift popup recurs
20+
/// every cycle even with Auto-apply silently enabled. (See commit 3202e9c, which
21+
/// only loosened the <i>read</i> heuristic and so didn't actually stop the loop.)</para>
22+
///
23+
/// <para><b>The reliable value.</b>
24+
/// <c>HKCU\Software\Microsoft\Windows\CurrentVersion\Search\BingSearchEnabled = 0</c>
25+
/// is the value Windows 11 actually honors for the search-box web/AI suggestion
26+
/// layer, and -- being an ordinary user setting rather than a policy -- it always
27+
/// persists and reads back. We make it the <i>sole</i> drift signal so a value
28+
/// Windows happens to ignore can never re-trigger the verify-fail/backoff/popup
29+
/// loop again. <c>IsDynamicSearchBoxEnabled = 0</c> (search highlights / the
30+
/// companion content) and the legacy <c>DisableSearchBoxSuggestions = 1</c> policy
31+
/// are still written best-effort for completeness, but are not part of the read.</para>
32+
///
33+
/// <para>Note: this does NOT disable the Windows Search index itself. Start menu
34+
/// search, Explorer search, and Outlook search continue to work; only the
35+
/// AI/web suggestion layer and highlights are silenced. A sign-out or Explorer
36+
/// restart may be needed before the change is visible.</para>
1337
/// </summary>
1438
public sealed class SettingsSearchAiMonitor : IMonitoredSetting
1539
{
1640
public string Id => "ai.settingssearch";
1741

42+
// Authoritative signal -- ordinary user setting, persists and reads back reliably.
43+
private const string SearchKey = @"Software\Microsoft\Windows\CurrentVersion\Search";
44+
private const string BingSearchVal = "BingSearchEnabled";
45+
// Search highlights / companion content.
46+
private const string SearchSettingsKey = @"Software\Microsoft\Windows\CurrentVersion\SearchSettings";
47+
private const string DynamicSearchVal = "IsDynamicSearchBoxEnabled";
48+
// Legacy policy -- best-effort only, unreliable on Win11, NOT read for drift.
1849
private const string PolicyKey = @"SOFTWARE\Policies\Microsoft\Windows\Explorer";
1950
private const string PolicyVal = "DisableSearchBoxSuggestions";
20-
private const string AdvancedKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
21-
private const string TaskbarCompanionVal = "TaskbarCompanion";
2251

2352
public IEnumerable<DriftItem> CheckDrift(AppConfig config)
2453
{
@@ -35,56 +64,73 @@ public IEnumerable<DriftItem> CheckDrift(AppConfig config)
3564
Description: desired
3665
? "Search box AI suggestions + taskbar companion -- re-enable"
3766
: "Search box AI suggestions + taskbar companion -- disable",
38-
CurrentValue: current.Value ? "On" : "Off (policy)",
39-
DesiredValue: desired ? "On" : "Off (policy)",
67+
CurrentValue: current.Value ? "On" : "Off",
68+
DesiredValue: desired ? "On" : "Off",
4069
AutoApply: pref.AutoApply,
4170
Apply: () => Task.Run(() => Apply(desired)),
4271
IsMonitored: pref.Monitor,
43-
RawBefore: current.Value ? "(default)" : "DisableSearchBoxSuggestions=1, TaskbarCompanion=0",
44-
RawDesired: desired ? "(deleted)" : "DisableSearchBoxSuggestions=1, TaskbarCompanion=0");
72+
RawBefore: current.Value ? "(default)" : "BingSearchEnabled=0, IsDynamicSearchBoxEnabled=0, DisableSearchBoxSuggestions=1",
73+
RawDesired: desired ? "(deleted)" : "BingSearchEnabled=0, IsDynamicSearchBoxEnabled=0, DisableSearchBoxSuggestions=1");
4574
}
4675

76+
/// <summary>
77+
/// Returns true when search-box AI/web suggestions are "on" (gaming-default),
78+
/// false when disabled, null when unreadable. Keyed solely on the reliable
79+
/// <see cref="BingSearchVal"/> so a Windows-ignored value can't cause a
80+
/// false-positive drift loop -- the failure mode this monitor twice hit.
81+
/// </summary>
4782
public static bool? ReadCurrent()
4883
{
4984
try
5085
{
51-
using var policy = Registry.CurrentUser.OpenSubKey(PolicyKey, writable: false);
52-
using var advanced = Registry.CurrentUser.OpenSubKey(AdvancedKey, writable: false);
53-
var disable = policy?.GetValue(PolicyVal) as int?;
54-
var companion = advanced?.GetValue(TaskbarCompanionVal) as int?;
55-
56-
// The PolicyVal (DisableSearchBoxSuggestions) is the primary signal
57-
// and authoritative. The TaskbarCompanion value is a belt-and-
58-
// suspenders write -- on many Windows builds the value name isn't
59-
// recognized by Explorer and the write silently doesn't stick. We
60-
// treat companion as "off" when it's absent OR explicitly 0; only
61-
// companion == 1 counts as "companion still on". Without this,
62-
// ReadCurrent would forever report "on" after Apply even though
63-
// the user-visible search box AI suggestions are actually off.
64-
bool searchSuggestionsOff = disable == 1;
65-
bool companionOff = companion != 1;
66-
bool off = searchSuggestionsOff && companionOff;
86+
using var search = Registry.CurrentUser.OpenSubKey(SearchKey, writable: false);
87+
var bing = search?.GetValue(BingSearchVal) as int?;
88+
// Disabled iff we explicitly set BingSearchEnabled = 0. Absent value
89+
// (fresh install) means suggestions are on -> reported as drift when
90+
// the user wants them off, which the first auto-apply then fixes.
91+
bool off = bing == 0;
6792
return !off;
6893
}
6994
catch { return null; }
7095
}
7196

7297
public static void Apply(bool on)
98+
{
99+
// Each write is independent and best-effort: the authoritative
100+
// BingSearchEnabled write lives under HKCU\...\Search (always
101+
// user-writable), so it succeeds even when the Policies hive is locked
102+
// on a managed device. Failures are swallowed per value rather than
103+
// aborting the whole apply.
104+
if (on)
105+
{
106+
DeleteValue(SearchKey, BingSearchVal);
107+
DeleteValue(SearchSettingsKey, DynamicSearchVal);
108+
DeleteValue(PolicyKey, PolicyVal);
109+
}
110+
else
111+
{
112+
SetValue(SearchKey, BingSearchVal, 0);
113+
SetValue(SearchSettingsKey, DynamicSearchVal, 0);
114+
SetValue(PolicyKey, PolicyVal, 1);
115+
}
116+
}
117+
118+
private static void SetValue(string subKey, string name, int value)
119+
{
120+
try
121+
{
122+
using var key = Registry.CurrentUser.CreateSubKey(subKey, writable: true);
123+
key?.SetValue(name, value, RegistryValueKind.DWord);
124+
}
125+
catch { }
126+
}
127+
128+
private static void DeleteValue(string subKey, string name)
73129
{
74130
try
75131
{
76-
using var policy = Registry.CurrentUser.CreateSubKey(PolicyKey, writable: true)!;
77-
using var advanced = Registry.CurrentUser.CreateSubKey(AdvancedKey, writable: true)!;
78-
if (on)
79-
{
80-
policy.DeleteValue(PolicyVal, throwOnMissingValue: false);
81-
advanced.DeleteValue(TaskbarCompanionVal, throwOnMissingValue: false);
82-
}
83-
else
84-
{
85-
policy.SetValue(PolicyVal, 1, RegistryValueKind.DWord);
86-
advanced.SetValue(TaskbarCompanionVal, 0, RegistryValueKind.DWord);
87-
}
132+
using var key = Registry.CurrentUser.OpenSubKey(subKey, writable: true);
133+
key?.DeleteValue(name, throwOnMissingValue: false);
88134
}
89135
catch { }
90136
}

src/GamerGuardian/Services/SettingDocs.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static string MechanismFor(string settingId)
4545
"ai.clicktodo" => @"HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsAI\DisableClickToDo + HKCU\Software\Microsoft\Windows\Shell\ClickToDo\DisableClickToDo",
4646
"ai.edge" => @"HKLM\SOFTWARE\Policies\Microsoft\Edge\{HubsSidebarEnabled, CopilotPageContext, GenAILocalFoundationalModelSettings, ComposeInlineEnabled, AllowBrowsingWithCopilot}",
4747
"ai.notepadpaint" => @"HKCU\Software\Microsoft\Notepad\RewriteEnabled + HKCU\...\Paint\{DisableCocreator, DisableImageCreator, DisableGenerativeErase} + HKCU\...\Applets\Paint\View\IsSignedUpForTargetingService + HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint\DisableImageCreator",
48-
"ai.settingssearch" => @"HKCU\SOFTWARE\Policies\Microsoft\Windows\Explorer\DisableSearchBoxSuggestions + HKCU\...\Explorer\Advanced\TaskbarCompanion",
48+
"ai.settingssearch" => @"HKCU\Software\Microsoft\Windows\CurrentVersion\Search\BingSearchEnabled (authoritative) + HKCU\...\SearchSettings\IsDynamicSearchBoxEnabled + HKCU\SOFTWARE\Policies\Microsoft\Windows\Explorer\DisableSearchBoxSuggestions (best-effort)",
4949
"ai.actions" => @"HKLM\SYSTEM\ControlSet001\Control\FeatureManagement\Overrides\8\{1853569164, 4098520719}\EnabledState (DWORD; 1 = force-disabled, 2 = force-enabled, absent = server default)",
5050
"ai.inputinsights" => @"HKCU\Software\Microsoft\InputPersonalization\RestrictImplicitTextCollection + HKCU\Software\Microsoft\input\Settings\InsightsEnabled",
5151
"ai.office" => @"HKCU\Software\Microsoft\Office\16.0\{Word\Options\EnableCopilot, Excel\Options\EnableCopilot, OneNote\Options\Copilot\CopilotEnabled} + HKLM\SOFTWARE\Policies\Microsoft\office\16.0\common\ai\training\general\disabletraining",
@@ -137,8 +137,11 @@ public static string ApplyCommandFor(string settingId, string rawDesired = "")
137137
@"Set-ItemProperty $pv -Name IsSignedUpForTargetingService -Value 0 -Type DWord; " +
138138
@"$hk='HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Paint'; New-Item $hk -Force | Out-Null; " +
139139
@"Set-ItemProperty $hk -Name DisableImageCreator -Value 1 -Type DWord",
140-
"ai.settingssearch" => @"Set-ItemProperty 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer' -Name DisableSearchBoxSuggestions -Value 1 -Type DWord; " +
141-
@"Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name TaskbarCompanion -Value 0 -Type DWord",
140+
"ai.settingssearch" => @"Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search' -Name BingSearchEnabled -Value 0 -Type DWord; " +
141+
@"$ss='HKCU:\Software\Microsoft\Windows\CurrentVersion\SearchSettings'; New-Item $ss -Force | Out-Null; " +
142+
@"Set-ItemProperty $ss -Name IsDynamicSearchBoxEnabled -Value 0 -Type DWord; " +
143+
@"$pe='HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer'; New-Item $pe -Force | Out-Null; " +
144+
@"Set-ItemProperty $pe -Name DisableSearchBoxSuggestions -Value 1 -Type DWord",
142145
"ai.actions" => @"$r='HKLM:\SYSTEM\ControlSet001\Control\FeatureManagement\Overrides\8'; " +
143146
@"foreach($id in 1853569164, 4098520719) { New-Item -Path ""$r\$id"" -Force | Out-Null; " +
144147
@"Set-ItemProperty -Path ""$r\$id"" -Name EnabledState -Value 1 -Type DWord }",
@@ -194,7 +197,7 @@ public static string VerifyCommandFor(string settingId)
194197
"ai.clicktodo" => @"(Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI' -Name DisableClickToDo -EA SilentlyContinue).DisableClickToDo",
195198
"ai.edge" => @"$k='HKLM:\SOFTWARE\Policies\Microsoft\Edge'; @{Hubs=(Get-ItemProperty $k -Name HubsSidebarEnabled -EA SilentlyContinue).HubsSidebarEnabled; Ctx=(Get-ItemProperty $k -Name CopilotPageContext -EA SilentlyContinue).CopilotPageContext; Gen=(Get-ItemProperty $k -Name GenAILocalFoundationalModelSettings -EA SilentlyContinue).GenAILocalFoundationalModelSettings; Compose=(Get-ItemProperty $k -Name ComposeInlineEnabled -EA SilentlyContinue).ComposeInlineEnabled; Browse=(Get-ItemProperty $k -Name AllowBrowsingWithCopilot -EA SilentlyContinue).AllowBrowsingWithCopilot}",
196199
"ai.notepadpaint" => @"$np='HKCU:\Software\Microsoft\Notepad'; $pt='HKCU:\Software\Microsoft\Windows\CurrentVersion\Paint'; @{Rewrite=(Get-ItemProperty $np -Name RewriteEnabled -EA SilentlyContinue).RewriteEnabled; Cocreator=(Get-ItemProperty $pt -Name DisableCocreator -EA SilentlyContinue).DisableCocreator}",
197-
"ai.settingssearch" => @"@{Disable=(Get-ItemProperty 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer' -Name DisableSearchBoxSuggestions -EA SilentlyContinue).DisableSearchBoxSuggestions; Companion=(Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name TaskbarCompanion -EA SilentlyContinue).TaskbarCompanion}",
200+
"ai.settingssearch" => @"@{Bing=(Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search' -Name BingSearchEnabled -EA SilentlyContinue).BingSearchEnabled; Dynamic=(Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\SearchSettings' -Name IsDynamicSearchBoxEnabled -EA SilentlyContinue).IsDynamicSearchBoxEnabled; Disable=(Get-ItemProperty 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer' -Name DisableSearchBoxSuggestions -EA SilentlyContinue).DisableSearchBoxSuggestions}",
198201
"ai.actions" => @"$r='HKLM:\SYSTEM\ControlSet001\Control\FeatureManagement\Overrides\8'; @{A=(Get-ItemProperty $r\1853569164 -Name EnabledState -EA SilentlyContinue).EnabledState; B=(Get-ItemProperty $r\4098520719 -Name EnabledState -EA SilentlyContinue).EnabledState}",
199202
"ai.inputinsights" => @"@{Restrict=(Get-ItemProperty 'HKCU:\Software\Microsoft\InputPersonalization' -Name RestrictImplicitTextCollection -EA SilentlyContinue).RestrictImplicitTextCollection; Insights=(Get-ItemProperty 'HKCU:\Software\Microsoft\input\Settings' -Name InsightsEnabled -EA SilentlyContinue).InsightsEnabled}",
200203
"ai.office" => @"@{Word=(Get-ItemProperty 'HKCU:\Software\Microsoft\Office\16.0\Word\Options' -Name EnableCopilot -EA SilentlyContinue).EnableCopilot; Excel=(Get-ItemProperty 'HKCU:\Software\Microsoft\Office\16.0\Excel\Options' -Name EnableCopilot -EA SilentlyContinue).EnableCopilot; OneNote=(Get-ItemProperty 'HKCU:\Software\Microsoft\Office\16.0\OneNote\Options\Copilot' -Name CopilotEnabled -EA SilentlyContinue).CopilotEnabled; Training=(Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\office\16.0\common\ai\training\general' -Name disabletraining -EA SilentlyContinue).disabletraining}",

src/GamerGuardian/Services/SettingDocsCatalog.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ private static IReadOnlyDictionary<string, string> Scenarios(params (string scen
354354
["ai.settingssearch"] = new(
355355
SettingId: "ai.settingssearch",
356356
DisplayName: "Search box AI suggestions + taskbar companion",
357-
What: "Two HKCU policies: DisableSearchBoxSuggestions (kills the AI/Copilot-flavored web suggestion layer in the Windows search box) and TaskbarCompanion (the floating Copilot widget Windows can dock next to the taskbar). HKCU only -- no UAC.",
357+
What: "Three HKCU values: BingSearchEnabled=0 (the value Windows 11 actually honors for the AI/web suggestion layer in the search box -- this is the authoritative one), IsDynamicSearchBoxEnabled=0 (search highlights / the companion content), and the legacy DisableSearchBoxSuggestions=1 policy (best-effort -- unreliable on Win11). HKCU only -- no UAC.",
358358
Why: "The search box's AI suggestion layer calls Microsoft web endpoints to suggest answers as you type. The taskbar companion is a floating overlay some Windows 11 builds enable by default. Both are noise for users who use the search box for files and apps.",
359359
HowItHelps: "Search box returns local files / apps only -- no web suggestions, no Copilot answers inline, no taskbar companion widget. Indexing itself (Start menu, Explorer, Outlook) is untouched.",
360360
Scenarios: Scenarios(
@@ -363,7 +363,7 @@ private static IReadOnlyDictionary<string, string> Scenarios(params (string scen
363363
("Privacy-conscious", "Off")),
364364
Recommended: "Off",
365365
Risks: "You lose the web-suggestion layer and the taskbar companion. Search itself works exactly as before.",
366-
ReversibleVia: "Delete DisableSearchBoxSuggestions from HKCU\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer and TaskbarCompanion from HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced."),
366+
ReversibleVia: "Delete BingSearchEnabled from HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Search, IsDynamicSearchBoxEnabled from HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\SearchSettings, and DisableSearchBoxSuggestions from HKCU\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer (or set them back to 1 / 1 / absent)."),
367367

368368
["ai.actions"] = new(
369369
SettingId: "ai.actions",

0 commit comments

Comments
 (0)