dotnet/wpf · error · ArgumentException
SR.HwndTarget_InvalidWindowHandle
Error message
SR.HwndTarget_InvalidWindowHandle
What it means
HwndTarget.AttachToHwnd validates the target window handle before attaching rendering to it. If GetWindowThreadProcessId ran but IsWindow reports the hwnd is no longer a valid window, it throws ArgumentException (SR.HwndTarget_InvalidWindowHandle) with parameter name 'hwnd'.
Solutions
- Verify the handle before passing it: call IsWindow(hwnd) and ensure it is nonzero and from a live process
- Re-acquire a fresh HWND from the host at attach time rather than caching one
- Check that the native host keeps the window alive for the lifetime of the HwndSource
Example fix
// before
var source = new HwndSource(0, 0, 0, 0, 0, "x", new IntPtr(0xDEADBEEF)); // throws
// after
if (!NativeMethods.IsWindow(hwnd)) throw new InvalidOperationException("host hwnd is gone");
var source = new HwndSource(0, 0, 0, 0, 0, "x", hwnd); Defensive patterns
Strategy: validation
Validate before calling
if (!UnsafeNativeMethods.IsWindow(new HandleRef(null, hwnd))) throw new InvalidOperationException("HWND is not valid"); Type guard
bool IsValidHwnd(IntPtr hwnd) => hwnd != IntPtr.Zero && NativeMethods.IsWindow(hwnd);
Try / catch
try { new HwndSource(...); } catch (ArgumentException) { /* re-acquire fresh hwnd from host */ } Prevention
- Never cache HWNDs across host-window lifetime
- Validate handles with IsWindow immediately before use
- Re-request the handle from the native host at attach time
When it happens
Trigger: Passing an hwnd from a destroyed window, a garbage/fake handle, or a handle whose owning process exited between obtaining it and constructing HwndTarget.
Common situations: Interop scenarios where the host app receives an HWND from native code or another process and immediately creates an HwndSource/HwndTarget over it; race conditions where the host window closes first.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- SR.Format(SR.AXNohWnd, GetType().Name)
- SR.HwndTarget_InvalidWindowProcess
- SR.HwndTarget_InvalidWindowThread
- SR.HwndTarget_WindowAlreadyHasContent
- 0x80070057
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/4316286d6ade3dab.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndTarget.cs:524
Debug.Assert(normalizedHwnd.Handle != IntPtr.Zero);
return normalizedHwnd;
}
/// <summary>
/// AttachToHwnd
/// </summary>
private void AttachToHwnd(IntPtr hwnd)
{
int processId = 0;
int threadId = UnsafeNativeMethods.GetWindowThreadProcessId(
new HandleRef(this, hwnd),
out processId
);
if (!UnsafeNativeMethods.IsWindow(new HandleRef(this, hwnd)))
{
throw new ArgumentException(
SR.HwndTarget_InvalidWindowHandle,
nameof(hwnd)
);
}
else if (processId != Environment.ProcessId)
{
throw new ArgumentException(
SR.HwndTarget_InvalidWindowProcess,
nameof(hwnd)
);
}
else if (threadId != SafeNativeMethods.GetCurrentThreadId())
{
throw new ArgumentException(
SR.HwndTarget_InvalidWindowThread,
nameof(hwnd)
);
}View on GitHub (pinned to 81131a70a4)