Skip to content

Legacy Script Editions

Mikhail Deynekin edited this page Oct 16, 2026 · 1 revision

Legacy Script Editions

Before TrayIconGuard became a native executable, this repository shipped — and for two generations refined — script-based fixes for the same problem: batch files, PowerShell scripts and .reg files. This page preserves that history with working verbatim examples taken from the v6.2 and v7.0.3 tags, explains precisely why the early artifacts failed, and records the audit that froze them. It is the problem-domain background for everything v8 does; the modern mechanics live in How Tray Visibility Works.

Warning

The v6-era files are deprecated and frozen. The repository's own notice (LEGACY-NOTICE.md, v7.0.3) says: “Do not extend or fix these files.” They remain in the tree only so that public raw URLs keep resolving. Do not deploy them: the .reg files write to invalid registry paths and ship a taskbar-corrupting StuckRects3 blob.


Contents


Timeline of the three generations

Era Tag Shape Primary mechanism
Scripts v6.2 (2025-11) Enable-AllTrayIcons.bat (“Configuration Tool 4.1”), Enable-AllTrayIcons.ps1 (“6.2 Enterprise”, 6,277 lines), enable-all-tray-icons.reg, disable-auto-hide.reg EnableAutoTray switch; comprehensive resets as an add-on
Phoenix v7.0.3 C# WPF GUI (app/), PowerShell module ShowAllTrayIcons (pwsh 7.6+), BAT edition (bat/Show-AllTrayIcons.bat), Pester tests, mechanics canon docs/HOW-IT-WORKS.md NotifyIconSettings\IsPromoted + watchers in all three editions
Aurora v8.0.0–8.4.0 single native C++17 exe (this wiki's subject) same store, event watcher, GUI + CLI + headless in one binary

v6 era: the EnableAutoTray approach (BAT)

The batch tool exposed enable|disable|status|backup|restore plus a /restart flag, kept its backup in %TEMP%\TrayIconsBackup.reg and logged to %TEMP%\Enable-AllTrayIcons.log. Its entire mechanism was the legacy switch (git show v6.2:Enable-AllTrayIcons.bat):

:: Registry Configuration
set "REGISTRY_PATH=HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer"
set "REGISTRY_VALUE=EnableAutoTray"
set "ENABLE_VALUE=0"
set "DISABLE_VALUE=1"

Reading the current state used a reg query parse, with 255 as the “value absent” sentinel — a pattern the later editions inherited:

:GET_CURRENT_TRAY_CONFIGURATION
reg query "!REGISTRY_PATH!" /v "!REGISTRY_VALUE!" >nul 2>&1
if !errorlevel! neq 0 exit /b 255
for /f "tokens=3" %%i in ('reg query "!REGISTRY_PATH!" /v "!REGISTRY_VALUE!" 2^>nul') do (
    exit /b %%i
)
exit /b 255

The backup/restore pair is still a tidy, dependency-free registry-safety pattern (write a .reg head, append either a deletion line or the current DWORD, re-import on restore):

(
echo Windows Registry Editor Version 5.00
echo.
echo [!REGISTRY_PATH!]
) > "!BACKUP_PATH!" 2>nul
if "!CURRENT_CONFIG!"=="255" (
    echo "!REGISTRY_VALUE!"=- >> "!BACKUP_PATH!" 2>nul
) else (
    echo "!REGISTRY_VALUE!"=dword:!CURRENT_CONFIG! >> "!BACKUP_PATH!" 2>nul
)

Why it was not enough: on Windows 10 1703+ and 11 the shell's per-icon store, not EnableAutoTray, decides visibility, so “enable” produced at best partial, legacy-component effects while per-icon hiding continued.

v6 era: the .reg files and their defects

enable-all-tray-icons.reg combined four ideas, three of which were wrong. Verbatim excerpts (git show v6.2:enable-all-tray-icons.reg):

; wrong home for HideSCA* (correct: ...\CurrentVersion\Policies\Explorer)
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer]
"HideSCAVolume"=-
"HideSCANetwork"=-
"HideSCAPower"=-

; wrong store path AND invented subkey names:
; the real store is HKCU\Control Panel\NotifyIconSettings with GUID subkeys
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NotifyIconSettings\Microsoft.VolumeControl]
"IsPromoted"=dword:00000001

; resolution-specific taskbar state: overwriting it corrupts other displays
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3]
"Settings"=hex:30,00,00,00,fe,ff,ff,ff,02,00,00,00,03,00,00,00,3e,00,00,00,\
  2e,00,00,00,00,00,00,00,9a,02,00,00,80,07,00,00,68,00,00,00

It also reset unrelated keys (Office UISettings, WindowsUpdate\UX, a OneDrive NameSpace value) that have no documented connection to tray visibility. The companion disable-auto-hide.reg mirrors the same defects in reverse and additionally deletes TrayNotify\UserPreferencesMask.

Defect Effect
HideSCA* deletes under …\Explorer no effect (values live under …\Policies\Explorer)
NotifyIconSettings under …\Explorer\ with Microsoft.VolumeControl-style names keys created where Windows never reads them
StuckRects3\Settings hex blob taskbar layout corruption on other resolutions/monitors
unrelated Office/Update/OneDrive values needless churn of unrelated settings

v6 era: the 6,277-line PowerShell “Enterprise” script

Enable-AllTrayIcons.ps1 at v6.2 is a monolith with a rich parameter surface: -Action Enable|Disable|Status|Rollback|Backup, -AllUsers, -RestartExplorer, -Force, -BackupRegistry, -CustomPath, -ExcludeCache, -CompressBackup, -Diagnostic, -Update, -HelpLevel, -LogPath, with SupportsShouldProcess and an exit-code table (0 success, 1 general error, 4 PowerShell-too-old, …). Two facts matter historically:

  1. Its “Group Policy / AllUsers” mode targeted HKCU:\Software\Policies\Microsoft\Windows\Explorer and the HKLM: equivalent with an EnableAutoTray value. No such Group Policy exists for per-icon promotion; the v7 audit called the claim misleading.
  2. Its comprehensive reset section did use the correct store path — evidence the real mechanism was known by 6.x but not yet made primary:
# v6.2, comprehensive reset section (line ~3654)
$settingsPath = "HKCU:\Control Panel\NotifyIconSettings"

while the primary configuration block still pointed at the legacy switch:

# v6.2 configuration hashtable (lines ~272-280)
RegistryPath = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer"
RegistryValue = "EnableAutoTray"
GroupPolicyUserPath = "HKCU:\Software\Policies\Microsoft\Windows\Explorer"
GroupPolicyMachinePath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer"

v7 era: corrected BAT edition

bat/Show-AllTrayIcons.bat (v7.0.3) is the script-era mechanics done right: correct paths up front, a build gate, a polling watch loop, and exit codes 0/1/2/3 that v8's CLI still uses. Header and path block:

:: Mechanism: HKCU\Control Panel\NotifyIconSettings\{id}\IsPromoted = 1
::            (the same store the Windows Settings toggle uses), plus the
::            legacy EnableAutoTray switch and HideSCA* policy cleanup at
::            their CORRECT registry locations.
set "REG_NIS=HKCU\Control Panel\NotifyIconSettings"
set "NIS_FULL=HKEY_CURRENT_USER\Control Panel\NotifyIconSettings"
set "REG_EXPLORER=HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer"
set "REG_POLICIES=HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer"

:: Windows build gate: NotifyIconSettings needs 1703 (15063)
for /f "tokens=4-6 delims=[]. " %%A in ('ver') do set "WINBUILD=%%C"
if !WINBUILD! LSS 15063 ( ... exit code 2 ... )

The scan-and-promote loop contains a subtle, documented reg.exe trap — the root key's own values (Version, MigrationStatus, UIOrderList) are printed indented and must not be counted as icons (the comment calls it defect P1-2):

:SCAN_AND_PROMOTE
rem findstr /b HKEY_ keeps only subkey lines; reg query also prints the root
rem key's own VALUES (Version, MigrationStatus, UIOrderList) as indented lines,
rem which must never be counted as icons (defect P1-2).
for /f "usebackq delims=" %%K in (`reg query "%REG_NIS%" 2^>nul ^| findstr /b "HKEY_"`) do (
    set "SUBKEY=%%K"
    if /i not "!SUBKEY!"=="!NIS_FULL!" (
        set /a COUNT_TOTAL+=1
        call :PROMOTE_KEY "!SUBKEY!"
    )
)

The watch loop is polling-based (timeout with a ping fallback for stripped images) — the BAT edition never had events:

:WATCH_LOOP
call :SCAN_AND_PROMOTE
if !COUNT_PROMOTED! GTR 0 (
    echo   [%DATE% %TIME%] Promoted !COUNT_PROMOTED! icon^(s^) ^(of !COUNT_TOTAL! registered^).
)
timeout /t !WATCH_INTERVAL! /nobreak >nul 2>&1
if errorlevel 1 ping -n !WATCH_INTERVAL! 127.0.0.1 >nul
goto :WATCH_LOOP

and the policy cleanup deletes only values that are actually present and equal to 1, from the correct path:

:CLEAR_HIDE_POLICIES
for %%V in (HideSCAVolume HideSCANetwork HideSCAPower) do (
    reg query "%REG_POLICIES%" /v %%V 2>nul | findstr /i "%%V" >nul && (
        reg delete "%REG_POLICIES%" /v %%V /f >nul 2>&1
        echo   Removed stale hide-policy: %%V
    )
)

v7 era: the ShowAllTrayIcons PowerShell module

The module (pwsh 7.6+) exported Get-TrayIcon, Set-TrayIcon, Enable-AllTrayIcons, Disable-AllTrayIcons, Start-TrayIconWatcher, Backup-TrayIconState, Restore-TrayIconState, Install-TrayIconAutostart, Uninstall-TrayIconAutostart, Reset-TrayIconCache, Restart-Explorer. Its watcher was genuinely event-driven via P/Invoke — the same API contract v8's C++ watcher uses:

// powershell/modules/ShowAllTrayIcons/Private/NativeMethods.ps1
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int RegNotifyChangeKeyValue(
    Microsoft.Win32.SafeHandles.SafeRegistryHandle hKey,
    bool bWatchSubtree,
    int dwNotifyFilter,
    Microsoft.Win32.SafeHandles.SafeWaitHandle hEvent,
    bool fAsynchronous);

public const int REG_NOTIFY_CHANGE_NAME     = 0x00000001;
public const int REG_NOTIFY_CHANGE_LAST_SET = 0x00000004;
public const int ERROR_KEY_DELETED          = 1018;

Start-TrayIconWatcher parameter contract (ranges included): -IntervalSec 1–3600 (default 3), -DebounceMs 100–10000 (default 400), -UsePolling, -ExcludeExecutable, -AutoRestartExplorer (60 s cooldown), -TimeoutSec, -OnPromoted, -AsJob (thread job), -WhatIf observe mode. The module also carried a post-mortem comment worth quoting for anyone compiling P/Invoke under PowerShell: passing -UsingNamespace 'System.Runtime.InteropServices' to Add-Type duplicates a using directive and fails with CS0105.

The audit that froze the legacy files

LEGACY-NOTICE.md (v7.0.3, independent audit dated 2026-10-13) freezes the four pre-7 files verbatim and summarizes their defects:

Legacy file Verdict v7 replacement
Enable-AllTrayIcons.bat legacy EnableAutoTray only; no watcher, no per-icon store bat/Show-AllTrayIcons.bat
Enable-AllTrayIcons.ps1 PS 5.1 monolith; “AllUsers/Group Policy” claims do not reflect real Windows behavior powershell/ module
enable-all-tray-icons.reg invalid HideSCA*/NotifyIconSettings paths; StuckRects3 data can corrupt taskbar layout module, correct paths only
disable-auto-hide.reg inverse of the above, same defects Disable-AllTrayIcons

Removal was deliberately deferred: public raw.githubusercontent.com URLs point at these files, and turning 200 into 404 would break unknown deployments.

What v8 kept and what it dropped

Kept in v8 Dropped after v6
NotifyIconSettings\IsPromoted as the only promotion mechanism EnableAutoTray as primary (kept only as optional belt)
RegNotifyChangeKeyValue watcher with debounce GP/AllUsers mode (fiction)
HideSCA* cleanup at the Policies path wrong-path writes of any kind
TrayNotify cache reset as explicit repair automatic cache deletion
Exit codes 0/1/2/3 .reg artifacts, StuckRects3 writes, unrelated key churn
BAT/PS watcher roles → --watch headless mode three-edition maintenance burden

See also

Clone this wiki locally