dotnet/wpf · warning · ElementNotAvailableException
ElementNotAvailableException
Error message
ElementNotAvailableException
What it means
GetTextWithinStructureRemoteBitness needs to read text from the process that owns the target hwnd via cross-process memory. If the SafeProcessHandle opened from the hwnd is invalid, the target window/process no longer exists, so UIAutomation throws ElementNotAvailableException — the element the client addressed is gone.
Solutions
- Verify the target element/window is still alive (IsOffscreen/Current.NativeWindowHandle, or re-find the element) before calling text retrieval.
- Catch ElementNotAvailableException and re-acquire the element from the desktop tree, then retry once.
- Check Process.GetProcessById / handle validity for the hwnd's PID before issuing the cross-process call.
- Ensure your client runs with sufficient integrity/privilege to open the target process (UIAccess, same elevation).
Example fix
// before
string text = GetTextWithinStructure(hwnd, ...); // throws if hwnd's process is dead
// after
if (IsWindow(hwnd))
{
try { text = GetTextWithinStructure(hwnd, ...); }
catch (ElementNotAvailableException) { text = null; }
} Defensive patterns
Strategy: try-catch
Validate before calling
[DllImport("user32.dll")] static extern bool IsWindow(IntPtr hWnd);
// before the call:
if (!IsWindow(hwnd)) return null; Type guard
static bool IsHwndUsable(IntPtr hwnd) => hwnd != IntPtr.Zero && IsWindow(hwnd);
Try / catch
try { text = GetTextWithinStructure(hwnd, ...); }
catch (ElementNotAvailableException) { text = null; /* re-acquire element */ } Prevention
- Check IsWindow/process liveness before cross-process UIA calls
- Do not hold hwnds across application restarts; re-resolve each session
- Match client and target elevation/integrity so process handles open
- Catch ElementNotAvailableException on every remote-element property read
When it happens
Trigger: Calling GetTextWithinStructure (which dispatches to GetTextWithinStructureRemoteBitness) for an hwnd whose process has exited or for which a process handle cannot be opened; SafeProcessHandle.IsInvalid is true immediately after construction.
Common situations: Automating an application that crashes or exits mid-run; racing window close during UI test teardown; elevated/protected processes that cannot be opened from a lower-integrity client; passing a stale hwnd captured earlier.
Related errors
- ElementNotAvailableException
- OutOfMemoryException
- Win32Exception
- ArgumentOutOfRangeException
- ElementNotAvailableException
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/36b174e3e26212cc.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/CommonXSendMessage.cs:74
// the max size for the string.
// Param "hwnd" the Window Handle
// Param "uMsg" the Windows Message
// Param "wParam" the Windows wParam
// Param "lParam" a pointer to a struct allocated on the stack
// Param "cbSize" the size of the structure
// Param "pszText" the address of a pointer to a string located with the structure referenced by the lParam
// Param "maxLength" the size of the string
// Param "remoteBitness" the bitness of the pointer contained within pszText
internal static unsafe string GetTextWithinStructureRemoteBitness(
IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam, int cbSize,
IntPtr pszText, int maxLength, ProcessorTypes remoteBitness, bool ignoreSendResult)
{
using (SafeProcessHandle hProcess = new SafeProcessHandle(hwnd))
{
if (hProcess.IsInvalid)
{
// assume that the hwnd was bad
throw new ElementNotAvailableException();
}
using (RemoteMemoryBlock rmem = new RemoteMemoryBlock(cbSize + (maxLength + 1) * sizeof(char), hProcess))
{
// Allocate the space for the object as well as the string
// Ensure proper allocation
if (rmem.IsInvalid)
{
return "";
}
// Force the string to be zero terminated
IntPtr remoteTextArea = new IntPtr((byte*)rmem.Address.ToPointer() + cbSize);
if (remoteBitness == ProcessorTypes.Processor32Bit)
{
// When the structure will be sent to a 32-bit process,
// pszText points to an int, not an IntPtr.View on GitHub (pinned to 81131a70a4)