{"record":{"id":"0df16efa12fef254","repo":"dotnet/wpf","slug":"elementnotavailableexception-hwndproxyelementprovider","errorCode":null,"errorMessage":"ElementNotAvailableException","messagePattern":"ElementNotAvailableException","errorType":"exception","errorClass":"ElementNotAvailableException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClient/MS/Internal/Automation/HwndProxyElementProvider.cs","lineNumber":146,"sourceCode":"                    str[0] = '\\0';\n                }\n\n                // get rid of any & used for shortcut keys\n                return Misc.StripMnemonic(str.ToString());\n            }\n            else if (idProp == AutomationElement.IsEnabledProperty)\n            {\n                return IsWindowReallyEnabled( _hwnd );\n            }\n            else if (idProp == AutomationElement.ProcessIdProperty)\n            {\n                // Get the pid of the process that the HWND lives in, not the\n                // pid that this proxy lives in\n                int pid;\n                // GetWindowThreadProcessId does use SetLastError().  So a call to GetLastError() would be meanless.\n                if (SafeNativeMethods.GetWindowThreadProcessId(_hwnd, out pid) == 0)\n                {\n                    throw new ElementNotAvailableException();\n                }\n\n                return pid;\n            }\n            else if( idProp == AutomationElement.NativeWindowHandleProperty )\n            {\n                // Need to downcast to Int32, since IntPtr's are not remotable.\n                return ((IntPtr) _hwnd).ToInt32();\n            }\n            else if (idProp == AutomationElement.HasKeyboardFocusProperty)\n            {\n                SafeNativeMethods.GUITHREADINFO gti = new SafeNativeMethods.GUITHREADINFO ();\n\n                if (!Misc.GetGUIThreadInfo(0, ref gti))\n                {\n                    return false;\n                }\n","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClient/MS/Internal/Automation/HwndProxyElementProvider.cs#L128-L164","documentation":"HwndProxyElementProvider.GetPropertyValue throws ElementNotAvailableException when SafeNativeMethods.GetWindowThreadProcessId fails (returns 0), meaning the underlying HWND is no longer valid — the element has disappeared, so no property (here ProcessIdProperty) can be retrieved.","triggerScenarios":"Calling GetPropertyValue(ProcessIdProperty) (or any property reaching this path) after the target window was destroyed; GetWindowThreadProcessId returns 0 because the HWND is stale.","commonSituations":"Automation runs against apps that close windows mid-scan; UIA clients enumerating desktop windows racing with app shutdown; flaky UI test suites when a dialog dismisses between enumeration and property fetch.","solutions":["Wrap GetPropertyValue in try/catch for ElementNotAvailableException and treat the element as gone.","Re-resolve the element via UIA's fresh element-from-handle/point before reading properties.","Use cache requests (BuildUpdatedCache) to fetch properties atomically in one cross-process call."],"exampleFix":"// before\nint pid = (int)element.GetCurrentPropertyValue(AutomationElement.ProcessIdProperty);\n// after\ntry { int pid = (int)element.GetCurrentPropertyValue(AutomationElement.ProcessIdProperty); }\ncatch (ElementNotAvailableException) { /* window closed; re-enumerate */ }","handlingStrategy":"try-catch","validationCode":"if (!SafeNativeMethods.IsWindow(hwnd))\n    throw new ElementNotAvailableException(); // element gone before property fetch","typeGuard":"static bool IsElementAvailable(AutomationReference e) => e != null && SafeNativeMethods.IsWindow(e.Hwnd);","tryCatchPattern":"try { pid = (int)element.GetCurrentPropertyValue(AutomationElement.ProcessIdProperty); }\ncatch (ElementNotAvailableException) { ReenumerateWindows(); }","preventionTips":["Catch ElementNotAvailableException around every cross-process property read.","Use UIA CacheRequest to fetch properties atomically.","Re-resolve elements rather than reusing stale AutomationElement references across waits."],"tags":["uiautomation","stale-handle","interop"],"backgroundTag":"element-not-available","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}