0X00000584

ERROR_CLASS_HAS_WINDOWS (0x584): Fix When a Window Class Has Open Windows

ERROR_CLASS_HAS_WINDOWS means you tried to unregister a window class while a window using it is still open. It's almost always a stuck app or a background process holding a hidden window.

I've seen ERROR_CLASS_HAS_WINDOWS (0x584) pop up in two places: in a C++ or C# app you're debugging, or on a workstation where some app refuses to close and a deploy script keeps failing. The message is blunt once you translate it. A window class — the template Windows uses to create a specific kind of window — can't be unregistered because at least one window built from that class is still alive somewhere on the desktop, or worse, hidden off-screen.

The Win32 call that triggers this is UnregisterClass. When it returns FALSE and GetLastError() is 1412 (0x584), the OS is telling you the class is still in use. Here's how to track it down, fastest path first.

Real-world trigger: A Citrix or RDP session where Outlook crashed but left an invisible rctrl_renwnd32 window behind. The next login script tried to reinitialize a shell extension, called UnregisterClass during cleanup, and died with 0x584 every single time. Killing the orphaned OUTLOOK.EXE process fixed it in ten seconds.

Fix #1 — The 30-second fix: kill the process holding the window

If you're not writing code and this error just appeared, a process is holding a window open. Close the app and retry whatever you were doing.

  1. Press Ctrl + Shift + Esc to open Task Manager.
  2. Click More details at the bottom if you only see a small list of apps.
  3. Look through the Processes tab for anything that looks like the app that failed. Outlook, Teams, a custom line-of-business tool, whatever triggered the error.
  4. Right-click it and choose End task. If Windows warns you about losing unsaved data, you've got the right process.
  5. Try your original action again.

After clicking End task, the process should vanish from the list within two or three seconds. If it lingers, move on to the next step.

You can also do this from the command line if you know the executable name:

taskkill /IM outlook.exe /F

Swap outlook.exe for whatever's holding you up. The /F forces the kill, which matters when the app has a hung window that's ignoring normal close requests.

Fix #2 — The 5-minute fix: hunt down the hidden window

Task Manager doesn't show hidden or off-screen windows. If you killed the obvious processes and the error keeps returning, you've got a ghost window from a process that's still running but not showing anything on screen.

Grab Process Explorer from Microsoft Sysinternals. It's a single 3 MB download, no install needed.

  1. Run procexp64.exe as administrator.
  2. Press Ctrl + F to open the Find Handle window.
  3. Type the class name you're trying to unregister. If you don't know it, skip to step 5.
  4. Click Search. It'll return any process that has a window, handle, or DLL referencing that name.
  5. If you don't know the class name, click View → Show Lower Pane, then right-click any process and pick Properties. The Windows tab lists every top-level window the process owns, including hidden ones.
  6. Look for windows with no title, tiny dimensions like 0x0, or handles listed as hidden.
  7. Right-click the offending process and select Kill Process or Kill Process Tree.

After the kill, the process disappears from the list immediately — Process Explorer is more aggressive than Task Manager. Retry your action.

One caveat: killing explorer.exe will blank your taskbar and desktop. It restarts automatically on most Windows 10 and 11 builds within 5 seconds. If it doesn't, press Ctrl + Shift + Esc, click File → Run new task, and type explorer.exe.

Fix #3 — The 15-minute fix: if you're the developer

If you're seeing 0x584 in your own code, the problem is that you're calling UnregisterClass before every window of that class has received WM_DESTROY and finished destroying. This is common in plugin architectures and in apps that spawn modal dialogs on worker threads.

Here's the pattern that bites people:

// This returns FALSE with GetLastError() == 1412
// because a modal dialog is still alive.
DestroyWindow(hMainWnd);
UnregisterClass(szClassName, hInstance); // <-- fails here

The real fix isn't to add a retry loop. It's to make sure every window has actually been destroyed before you unregister the class. DestroyWindow is asynchronous when called from outside the window's thread — it posts WM_DESTROY and returns. The window is still there for a few milliseconds.

Two things to do:

  1. Call UnregisterClass only after the thread that owns the window has exited, or from the same thread that owns every window of the class.
  2. If you must unregister from a different thread, use EnumThreadWindows to enumerate and destroy every window first, then post a sentinel message and wait for the owning thread to process it.

A quick diagnostic before you rewrite anything — log the class name and count windows before unregistering:

int count = 0;
EnumWindows([](HWND h, LPARAM lp) -> BOOL {
    wchar_t cls[256];
    GetClassNameW(h, cls, 256);
    if (wcscmp(cls, L"YourClass") == 0) {
        (*(int*)lp)++;
        // Also check: IsWindowVisible(h)
    }
    return TRUE;
}, (LPARAM)&count);
// Log count before UnregisterClass.

If count is anything but zero, you've got your culprit. Track down which code path created that window and never destroyed it. Nine times out of ten it's an error-handling branch that returns early without calling DestroyWindow.

Registry paths worth checking

Window classes registered globally (not per-process) leave entries under the registry here:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved
HKEY_CLASSES_ROOT\CLSID\{your-guid}\InprocServer32

If a shell extension is the offender, its class registration survives a reboot. Disable the extension via Autoruns (also from Sysinternals) before you delete anything. Deleting a CLSID key that an installed product depends on will break that product — I've watched people spend a full day re-installing Office over this.

When none of this works

If the error survives a full reboot, something is registering the class and creating a window during startup. That means a service, a scheduled task, or an entry under HKCU\Software\Microsoft\Windows\CurrentVersion\Run. Open Autoruns, hide Microsoft entries, and look for anything that spawns a background window. Disable it, reboot, and see if 0x584 goes away. If it does, you've found the app that's been holding the class open — and the fix is a support ticket to whoever makes it, not a hack on your end.

Do not install a "Windows error fixer" utility for this. ERROR_CLASS_HAS_WINDOWS is not a corrupted system file. It's a legitimate signal from the OS that something is still using a resource. Cleaners won't touch it and one of them will probably make things worse.

Related Errors in Windows Errors
0X000035F2 Fix ERROR_IPSEC_IKE_QM_ACQUIRE_DROP 0X000035F2 0X00002090 Fix ERROR_DS_ALIAS_POINTS_TO_ALIAS (0X00002090) in Active Directory 0XC00D11AA Fix NS_E_WMP_WMDM_INCORRECT_RIGHTS (0XC00D11AA) Sync Error 0X00000253 0X00000253: The Reply Message Mismatch Trap

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.