dotnet/wpf · error · Win32Exception

Win32 error

Error message

Win32 error

What it means

Popup's internal window-anchoring helper walks sibling HWNDs with GetWindow(GW_HWNDPREV); when the Win32 call chain fails or returns an unexpected state it throws new Win32Exception(), which carries the last Win32 error as its message. This is an OS-level failure while positioning the popup's HWND relative to others.

Solutions

  1. Inspect Win32Exception.NativeErrorCode to identify the Win32 failure and the lifecycle race causing it.
  2. Guard popup open/close ordering: don't close the owner window while a popup is being positioned (defer Close with Dispatcher).
  3. Retry the operation — transient races during session changes (RDP, lock screen) usually clear.
  4. Keep the WPF runtime current; several popup HWND race fixes shipped in .NET/WPF servicing releases.
Defensive patterns

Strategy: retry

Validate before calling

if (!popup.IsOpen) return; // don't operate on a popup whose HWND may be gone

Try / catch

try { popup.IsOpen = true; }
catch (Win32Exception wex) { Log(wex.NativeErrorCode); /* retry after dispatcher idle */ }

Prevention

When it happens

Trigger: Win32 GetWindow failing during popup z-order/positioning (invalid or destroyed HWND, window closed concurrently, Win32 error such as ERROR_INVALID_WINDOW_HANDLE); usually under stress, rapid open/close, or across desktops/session transitions (e.g. RDP disconnect).

Common situations: Popups shown during window teardown, heavy automation/UITests, RDP session changes, or low-memory conditions where HWNDs are destroyed while the popup is being positioned.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/92274d0d9da6fe40. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/Popup.cs:3220

                StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH);
                // Search up from the last one until we find the first weboc hwnd.
                while (lastHwnd != IntPtr.Zero)
                {
                    if (UnsafeNativeMethods.GetClassName(new HandleRef(null, lastHwnd), sb, NativeMethods.MAX_PATH) != 0)
                    {
                        if (string.Equals(sb.ToString(), WebOCWindowClassName, StringComparison.OrdinalIgnoreCase))
                        {
                            break;
                        }
                        else
                        {
                            lastHwnd = UnsafeNativeMethods.GetWindow(new HandleRef(null, lastHwnd), NativeMethods.GW_HWNDPREV);
                        }
                    }
                    else
                    {
                        throw new Win32Exception();
                    }
                }

                return lastHwnd;
            }

            internal void SetHitTestable(bool hitTestable)
            {

                // get the window handle
                IntPtr handle = Handle;

                Int32 styles = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, handle), NativeMethods.GWL_EXSTYLE);

                int flags = styles;

                if (((flags & NativeMethods.WS_EX_TRANSPARENT) == 0) != hitTestable)
                {

View on GitHub (pinned to 81131a70a4)