{"record":{"id":"2cf8c1ec57197f6c","repo":"dotnet/wpf","slug":"sr-penservice-windowalreadyregistered","errorCode":null,"errorMessage":"SR.PenService_WindowAlreadyRegistered","messagePattern":"SR\\.PenService_WindowAlreadyRegistered","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/WispLogic.cs","lineNumber":3157,"sourceCode":"        /////////////////////////////////////////////////////////////////////\n        internal void RegisterHwndForInput(InputManager inputManager, PresentationSource inputSource)\n        {\n            HwndSource hwndSource = (HwndSource)inputSource;\n\n            GetAndCacheTransformToDeviceMatrix(hwndSource);\n\n            // Keep track so we don't bother looking for changes if someone happened to query this before\n            // an Avalon window was created where we get TabletAdd/Removed notification.\n            bool initializedTablets = (_tabletDeviceCollection == null);\n\n            // This causes EnableCore to be called on TabletPC systems which enabled stylus input!\n            WispTabletDeviceCollection tablets = WispTabletDevices;\n\n            lock (__penContextsLock)\n            {\n                if (__penContextsMap.ContainsKey(inputSource))\n                {\n                    throw new InvalidOperationException(SR.PenService_WindowAlreadyRegistered);\n                }\n\n                PenContexts penContexts = new PenContexts(StylusLogic.GetCurrentStylusLogicAs<WispLogic>(), inputSource);\n\n                __penContextsMap[inputSource] = penContexts;\n\n                // If FIRST one set this as the one to manage TabletAdded/Removed notifications.\n                if (__penContextsMap.Count == 1)\n                {\n                    // Make sure our view of TabletDevices is up to date we didn't just cause it\n                    // to be initialized and we had some real tablet devices.\n                    if (!initializedTablets && tablets.Count > 0)\n                    {\n                        tablets.UpdateTablets();\n\n                        // Update the last known device count.\n                        _lastKnownDeviceCount = GetDeviceCount();\n                    }","sourceCodeStart":3139,"sourceCodeEnd":3175,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/WispLogic.cs#L3139-L3175","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nOnLoaded((s,e) => StylusLogic.RegisterStylusPointProcessor(myProcessor, source));\n// after\nif (!registered.Contains(source)) { registered.Add(source); StylusLogic.RegisterStylusPointProcessor(myProcessor, source); }","handlingStrategy":"validation","validationCode":"if (registeredSources.Contains(inputSource)) return; // skip duplicate registration\nregisteredSources.Add(inputSource);","typeGuard":null,"tryCatchPattern":"try { RegisterStylusPointProcessor(proc, source); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"already registered\")) { /* treat as success, idempotent */ }","preventionTips":["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"],"tags":["wpf","stylus","pen","duplicate-registration"],"backgroundTag":"file-already-exists","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"}