dotnet/wpf · error · InvalidOperationException
SR.PenService_WindowAlreadyRegistered
Error message
SR.PenService_WindowAlreadyRegistered
What it means
WispLogic.RegisterInputSource (WispLogic.cs:3157) throws InvalidOperationException(SR.PenService_WindowAlreadyRegistered) when RegisterStylusPointProcessor/InputSource registration finds the given PresentationSource (window) already present in __penContextsMap. Each HwndSource can be registered with the stylus/pen service only once.
Solutions
- Guard registration with a check that the source is not already registered (track your own set of registered sources).
- Pair every registration with an unregistration on window/source close.
- Move registration code out of handlers that can fire multiple times (e.g. Loaded) into a once-only initialization path.
Example fix
// before
OnLoaded((s,e) => StylusLogic.RegisterStylusPointProcessor(myProcessor, source));
// after
if (!registered.Contains(source)) { registered.Add(source); StylusLogic.RegisterStylusPointProcessor(myProcessor, source); } Defensive patterns
Strategy: validation
Validate before calling
if (registeredSources.Contains(inputSource)) return; // skip duplicate registration registeredSources.Add(inputSource);
Try / catch
try { RegisterStylusPointProcessor(proc, source); } catch (InvalidOperationException ex) when (ex.Message.Contains("already registered")) { /* treat as success, idempotent */ } Prevention
- Make stylus registration idempotent with your own source set
- Pair register/unregister with window Loaded/Unloaded (or SourceInitialized/Closed)
- Avoid registration in handlers that can fire repeatedly
When it happens
Trigger: Calling WispLogic-based registration APIs (e.g. StylusLogic.RegisterStylusPointProcessor or internal AddPenContexts path) twice with the same PresentationSource, or re-registering a window whose registration was never torn down.
Common situations: Host apps registering a custom stylus plug-in multiple times (e.g. on every window load without unload pairing); window re-shown/recycled after source teardown failed; duplicate initialization in derived Window classes.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- SR.PenService_WindowNotRegistered
- captureMode
- captureMode
- InvalidOperationException
- SR.Format(SR.Enum_Invalid, nameof(actions))
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/2cf8c1ec57197f6c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/WispLogic.cs:3157
/////////////////////////////////////////////////////////////////////
internal void RegisterHwndForInput(InputManager inputManager, PresentationSource inputSource)
{
HwndSource hwndSource = (HwndSource)inputSource;
GetAndCacheTransformToDeviceMatrix(hwndSource);
// Keep track so we don't bother looking for changes if someone happened to query this before
// an Avalon window was created where we get TabletAdd/Removed notification.
bool initializedTablets = (_tabletDeviceCollection == null);
// This causes EnableCore to be called on TabletPC systems which enabled stylus input!
WispTabletDeviceCollection tablets = WispTabletDevices;
lock (__penContextsLock)
{
if (__penContextsMap.ContainsKey(inputSource))
{
throw new InvalidOperationException(SR.PenService_WindowAlreadyRegistered);
}
PenContexts penContexts = new PenContexts(StylusLogic.GetCurrentStylusLogicAs<WispLogic>(), inputSource);
__penContextsMap[inputSource] = penContexts;
// If FIRST one set this as the one to manage TabletAdded/Removed notifications.
if (__penContextsMap.Count == 1)
{
// Make sure our view of TabletDevices is up to date we didn't just cause it
// to be initialized and we had some real tablet devices.
if (!initializedTablets && tablets.Count > 0)
{
tablets.UpdateTablets();
// Update the last known device count.
_lastKnownDeviceCount = GetDeviceCount();
}View on GitHub (pinned to 81131a70a4)