{"record":{"id":"58f538cd4bf5b588","repo":"stride3d/stride","slug":"the-given-window-is-already-registered-as-a-clipboard","errorCode":null,"errorMessage":"The given {window} is already registered as a clipboard listener.","messagePattern":"The given (.+?) is already registered as a clipboard listener\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Wpf/Interop/ClipboardMonitor.cs","lineNumber":38,"sourceCode":"        /// <summary>\n        /// Raised when the clipboard has changed and contains text.\n        /// </summary>\n        /// <remarks>The sender of this event a window that was previously registered as a clipboard viewer with <see cref=\"RegisterListener\"/>.</remarks>\n        public static event EventHandler<EventArgs> ClipboardTextChanged;\n\n        /// <summary>\n        /// Registers the given <paramref name=\"window\"/> as a clipboard viewer.\n        /// </summary>\n        /// <param name=\"window\"></param>\n        /// <exception cref=\"ArgumentNullException\">window is <c>null</c></exception>\n        /// <exception cref=\"InvalidOperationException\">window is already registered.</exception>\n        public static void RegisterListener([NotNull] Window window)\n        {\n            if (window == null) throw new ArgumentNullException(nameof(window));\n\n            HwndSource hwndSource;\n            if (Listeners.TryGetValue(window, out hwndSource))\n                throw new InvalidOperationException($\"The given {window} is already registered as a clipboard listener.\");\n\n            hwndSource = GetHwndSource(window);\n            if (hwndSource == null)\n                return;\n\n            Listeners.Add(window, hwndSource);\n\n            window.Dispatcher.Invoke(() =>\n            {\n                // start processing window messages\n                hwndSource.AddHook(WinProc);\n                // set the window as a viewer\n                hwndNextViewer = NativeHelper.SetClipboardViewer(hwndSource.Handle);\n            });\n        }\n\n        /// <summary>\n        /// Unregisters the given <paramref name=\"window\"/> as a clipboard viewer.","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Wpf/Interop/ClipboardMonitor.cs#L20-L56","documentation":"ClipboardMonitor.RegisterListener throws InvalidOperationException when the given Window is already present in the static Listeners dictionary, because a window can only hook the clipboard chain once per monitor instance.","triggerScenarios":"Calling ClipboardMonitor.RegisterListener(window) twice for the same Window instance without unregistering in between; re-registering after a window was shown/hidden but not unregistered.","commonSituations":"Registering in both a Loaded handler and a constructor; re-registering after theme/appearance change re-triggers initialization; forgetting to call the unregister counterpart on window close before reopening.","solutions":["Call the unregister/deregister method for the window before calling RegisterListener again.","Track registration state per window (e.g. a bool or Listeners.ContainsKey check) and skip duplicate registrations.","Register once in the window's SourceInitialized/Loaded handler with a guard flag.","Ensure cleanup runs on Closed so the same window can be safely re-registered later."],"exampleFix":"// before\nprotected override void OnSourceInitialized(EventArgs e)\n{\n    base.OnSourceInitialized(e);\n    ClipboardMonitor.RegisterListener(this);\n    ClipboardMonitor.RegisterListener(this); // throws on 2nd call\n}\n// after\nprotected override void OnSourceInitialized(EventArgs e)\n{\n    base.OnSourceInitialized(e);\n    if (!_registered)\n    {\n        ClipboardMonitor.RegisterListener(this);\n        _registered = true;\n    }\n}","handlingStrategy":"try-catch","validationCode":"if (!ClipboardMonitorIsRegistered(this))\n    ClipboardMonitor.RegisterListener(this);","typeGuard":"static bool IsRegistered(Window w) => !ClipboardMonitorRegisteredWindows.Contains(w); // track locally","tryCatchPattern":"try { ClipboardMonitor.RegisterListener(this); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already registered\")) { /* already listening */ }","preventionTips":["Register exactly once, guarded by a flag, in SourceInitialized/Loaded","Always unregister in Closed so re-registration is safe","Avoid registering in both constructor and Loaded handlers"],"tags":["wpf","invalidoperation","clipboard","duplicate-registration"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}