{"record":{"id":"a4c093d0318214d4","repo":"dotnet/wpf","slug":"elementnotavailableexception-windowsmenu","errorCode":null,"errorMessage":"ElementNotAvailableException","messagePattern":"ElementNotAvailableException","errorType":"exception","errorClass":"System.Windows.Automation.ElementNotAvailableException","httpStatus":null,"severity":"warning","filePath":"src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsMenu.cs","lineNumber":535,"sourceCode":"            System.Diagnostics.Debug.WriteLine(sb.ToString());\n#endif\n\n            return result;\n        }\n\n        // Return menuItem object which is a hierarchical parent of the given menu (specified via hwnd)\n        // return NULL in the case when menu does not have a parent (e.g. Context menu)\n        // NOTE: this method should not be called for the menuItem that lives on the System or Menubar\n        internal static MenuItem GetHierarchyParent(IntPtr hwnd)\n        {\n            int ownerMenuItemPos = -1;\n            IntPtr menuParent = IntPtr.Zero;\n            IntPtr hwndParent = IntPtr.Zero;\n\n            IntPtr menu = HmenuFromHwnd(hwnd);\n            if (menu == IntPtr.Zero)\n            {\n                throw new ElementNotAvailableException();\n            }\n            MenuType currentType = GetSubMenuType(hwnd, menu);\n            MenuType parentType = MenuType.Toplevel;\n\n            if (currentType == MenuType.Submenu)\n            {\n                if (!GetSubMenuParent(hwnd, out menuParent, out hwndParent, out ownerMenuItemPos, out parentType))\n                {\n                    return null;\n                }\n\n                ProxyFragment parent = null;\n                if (parentType == MenuType.Toplevel)\n                {\n                    // Top Level Menu.\n                    // We need to have the parenthood defined in the same way as if it was done\n                    // from the non client area code.\n","sourceCodeStart":517,"sourceCodeEnd":553,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsMenu.cs#L517-L553","documentation":"ElementNotAvailableException is the UI Automation proxy signal that the underlying Windows element has vanished or is no longer accessible. In WindowsMenu.GetHierarchyParent, the code asks the target hwnd for its menu handle (HmenuFromHwnd); when the OS returns IntPtr.Zero the menu no longer exists (the window was closed, destroyed, or never had a menu), so the proxy throws because it cannot compute a hierarchy parent for a dead element.","triggerScenarios":"Calling AutomationElement.TreeWalker (RawViewWalker/ControlViewWalker) GetParent/GetFirstChild on a WindowsMenu proxy whose hwnd's menu handle has become zero — typically because the window's menu was destroyed or the window closed between the element being found and the parent being resolved. Reached via callers WindowsMenu, FixMDIMenuType, and MenuEvents during tree walks and MDI menu restructuring.","commonSituations":"UIA clients walking menus of apps being closed or resized; MDI applications whose menu bar is rebuilt/replaced while automation is traversing it; tests that hold AutomationElement references across window close; timing races where the element is cached after the native menu is gone.","solutions":["Re-fetch the element instead of using stale references: after any window close/menu rebuild, find the element again via AutomationElement.RootElement.FindFirst rather than walking from the old node.","Wrap tree-walk calls (TreeWalker.GetParent/GetFirstChild) in try/catch for ElementNotAvailableException and treat the element as gone.","Use FindAll/FindFirst with a TreeScope query instead of manual walker traversal; UIA core handles vanished elements more gracefully there.","Ensure the automation target window is fully initialized and still alive before walking its menu (check AutomationElement.IsOffscreen / NativeWindowHandle and process HasExited)."],"exampleFix":"// before\nAutomationElement parent = TreeWalker.ControlViewWalker.GetParent(menuElement);\n// after\nAutomationElement parent;\ntry\n{\n    parent = TreeWalker.ControlViewWalker.GetParent(menuElement);\n}\ncatch (ElementNotAvailableException)\n{\n    parent = null; // window/menu closed; re-find element if needed\n}","handlingStrategy":"try-catch","validationCode":"// before walking, check element is still alive\nif (menuElement == null || (bool)menuElement.GetCurrentPropertyValue(AutomationElement.IsOffscreenProperty))\n    return null;\nvar hwnd = (IntPtr)menuElement.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty);\nif (hwnd == IntPtr.Zero) return null;","typeGuard":"static bool IsAlive(AutomationElement el)\n{\n    try { var _ = el.Current.Name; return true; }\n    catch (ElementNotAvailableException) { return false; }\n}","tryCatchPattern":"try\n{\n    parent = TreeWalker.ControlViewWalker.GetParent(menuElement);\n}\ncatch (ElementNotAvailableException)\n{\n    parent = null; // stale element; re-find via FindFirst if needed\n}","preventionTips":["Re-find elements after window close or menu rebuild instead of walking from cached nodes","Catch ElementNotAvailableException on every TreeWalker traversal step","Verify the target process/window still exists before automation","Prefer FindFirst/FindAll queries over manual walker traversal"],"tags":["uiautomation","winforms","menu","stale-element"],"backgroundTag":"stale-uia-element","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}