Last active
February 15, 2026 20:36
-
-
Save cw2k/26e1818303e0061e38d6a612ac52b1d5 to your computer and use it in GitHub Desktop.
Windows10: Removes Nag "Activate Windows" in Windows 10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| RemoveNag2_ActivateWindows.ps1 | |
| -------------------------------- | |
| Purpose: | |
| Removes that "Activate Windows" watermark created by explorer.exe | |
| on Windows 10 systems. | |
| The script attempts a clean shutdown of the hidden Worker Window | |
| hosting the watermark by sending WM_DESTROY and WM_CLOSE. | |
| If the window survives, it falls back to SW_HIDE. | |
| Source Reference: | |
| Self: https://gist.github.com/cw2k/26e1818303e0061e38d6a612ac52b1d5 | |
| Based on the technique described by Paul π on SuperUser: | |
| https://superuser.com/a/1908410 | |
| Retrieved 2026‑02‑14, License: CC BY‑SA 4.0 | |
| Auto‑Run Instructions: | |
| 1. Create a shortcut (*.lnk) to this script. | |
| 2. Edit the shortcut target and prepend: | |
| powershell.exe -ExecutionPolicy Bypass -File | |
| 3. Test the shortcut. | |
| 4. Move it into the Startup folder: | |
| shell:startup | |
| Notes: | |
| • This script does NOT modify system files or licensing components. | |
| • It only interacts with the watermark window created by explorer.exe. | |
| • WM_DESTROY does not fully destroy the window; WM_CLOSE is required. | |
| • If explorer recreates the watermark, the script can be run again. | |
| #> | |
| function Hide-Watermark { | |
| # Load Win32 API definitions once | |
| if (-not ([System.Management.Automation.PSTypeName]'Win32').Type) { | |
| Add-Type @" | |
| using System; | |
| using System.Runtime.InteropServices; | |
| public class Win32 | |
| { | |
| [DllImport("user32.dll")] | |
| public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); | |
| [DllImport("user32.dll", SetLastError=true)] | |
| public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); | |
| [DllImport("user32.dll")] | |
| public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); | |
| } | |
| "@ | |
| } | |
| $className = "Worker Window" | |
| $windowTitle = "" | |
| # Try to locate the watermark window | |
| $hWnd = [Win32]::FindWindow($className, $windowTitle) | |
| if ($hWnd -ne [IntPtr]::Zero) { | |
| $hex = ("0x{0:X}" -f $hWnd.ToInt64()) | |
| "Class: '$className' handle: $hex" | |
| "Sending WM_DESTROY and WM_CLOSE ..." | |
| $WM_DESTROY = 0x0002 | |
| $WM_CLOSE = 0x0010 | |
| [void][Win32]::SendMessage($hWnd, $WM_DESTROY, [IntPtr]::Zero, [IntPtr]::Zero) | |
| [void][Win32]::SendMessage($hWnd, $WM_CLOSE, [IntPtr]::Zero, [IntPtr]::Zero) | |
| $hWnd = [Win32]::FindWindow($className, $windowTitle) | |
| if ($hWnd -eq [IntPtr]::Zero) { | |
| "'Activate Windows' watermark successfully destroyed." | |
| } | |
| else { | |
| "Fallback: hiding watermark window ..." | |
| $SW_SHOW = 5 | |
| $SW_HIDE = 0 | |
| [Win32]::ShowWindow($hWnd, $SW_HIDE) | |
| } | |
| } | |
| else { | |
| # If watermark not found, check if Explorer is running | |
| $hWnd = [Win32]::FindWindow("Shell_TrayWnd", $windowTitle) | |
| if ($hWnd -eq [IntPtr]::Zero) { | |
| Write-Error "Explorer.exe is not running." | |
| } | |
| else { | |
| "'Activate Windows' watermark not found or already removed." | |
| } | |
| } | |
| } | |
| Hide-Watermark |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And here the WndProc from the M$ Explorer.exe for the Watermark
An here if you ever wondered what
HKCU\Software\Microsoft\Windows\CurrentVersion\Watermark
Timestamp
is used for:
... it is triggered through msg NIN_BALLOONUSERCLICK
And just updates every 24 hour the timestampvalue
(maybe to read out by some other programm)