{"record":{"id":"a89657958a7dbf93","repo":"babalae/better-genshin-impact","slug":"error-a89657","errorCode":null,"errorMessage":"相对鼠标捕获工厂未注册","messagePattern":"相对鼠标捕获工厂未注册","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs","lineNumber":75,"sourceCode":"        try\n        {\n            SystemControl.ActivateWindow();\n\n            _logger.LogInformation(\"录制：{Text}\", \"实时任务已暂停\");\n            _logger.LogInformation(\"注意：录制时遇到主界面（鼠标永远在界面中心）和其他界面（鼠标可自由移动，比如地图等）的切换，请把手离开鼠标等待录制模式切换日志\");\n\n            for (var i = 3; i >= 1; i--)\n            {\n                _logger.LogInformation(\"{Sec}秒后启动录制...\", i);\n                await Task.Delay(1000);\n            }\n\n            TaskTriggerDispatcher.Instance().StopTimer();\n            taskTriggerStopped = true;\n\n            _recorder = new KeyMouseRecorder();\n            var monitorFactory = App.GetService<IRelativeMouseInputMonitorFactory>()\n                                 ?? throw new InvalidOperationException(\"相对鼠标捕获工厂未注册\");\n            _relativeMouseSubscription = monitorFactory\n                .Get(inputType)\n                .Subscribe(RelativeMouseMoved);\n\n            _timer.Start();\n            Status = KeyMouseRecorderStatus.Recording;\n\n            _logger.LogInformation(\"录制：已启动，相对鼠标捕获方式：{InputType}\", inputType);\n            return true;\n        }\n        catch (Exception ex)\n        {\n            _timer.Stop();\n            try\n            {\n                _relativeMouseSubscription?.Dispose();\n            }\n            catch (Exception disposeException)","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs#L57-L93","documentation":"GlobalKeyMouseRecord.StartRecord resolves IRelativeMouseInputMonitorFactory from the DI container via App.GetService and throws InvalidOperationException when it returns null. The factory is registered in App.xaml.cs as a singleton, so this throw indicates the service was requested before the DI container was built or in a context where that registration is absent.","triggerScenarios":"Calling GlobalKeyMouseRecord.Instance.StartRecord(...) before App startup completes the DI registration, or running in a test/host that never registered IRelativeMouseInputMonitorFactory.","commonSituations":"Unit test harness without ServiceProvider; background task started during construction before DI is ready; refactor removed the App.xaml.cs registration; calling from a context where App.ServiceProvider is not yet assigned.","solutions":["Ensure App.xaml.cs registers services.AddSingleton<IRelativeMouseInputMonitorFactory, RelativeMouseInputMonitorFactory>().","Only call StartRecord after the application DI container is initialized (e.g. after the startup page loads).","In tests, register a mock IRelativeMouseInputMonitorFactory before exercising StartRecord.","Guard the call with App.GetService(...) != null and warn the user instead of throwing."],"exampleFix":"// before\nvar monitorFactory = App.GetService<IRelativeMouseInputMonitorFactory>()\n    ?? throw new InvalidOperationException(\"相对鼠标捕获工厂未注册\");\n\n// after: graceful user-facing error\nvar monitorFactory = App.GetService<IRelativeMouseInputMonitorFactory>();\nif (monitorFactory == null)\n{\n    await ThemedMessageBox.ErrorAsync(\"录制组件未就绪，请稍后重试\", \"键鼠录制启动失败\");\n    return false;\n}","handlingStrategy":"validation","validationCode":"var factory = App.GetService<IRelativeMouseInputMonitorFactory>();\nif (factory is null)\n{\n    await ThemedMessageBox.ErrorAsync(\"录制组件未就绪，请稍后重试\", \"键鼠录制启动失败\");\n    return false;\n}\n// then proceed with factory.Get(inputType)","typeGuard":null,"tryCatchPattern":"try { return await StartRecord(inputType); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"相对鼠标捕获工厂未注册\"))\n{ _logger.LogError(ex, \"DI not ready for recording.\"); await ThemedMessageBox.ErrorAsync(ex.Message, \"键鼠录制启动失败\"); return false; }","preventionTips":["Confirm App.xaml.cs keeps services.AddSingleton<IRelativeMouseInputMonitorFactory, RelativeMouseInputMonitorFactory>().","Do not call StartRecord before the DI container is built (e.g. during early construction).","In tests, register a mock IRelativeMouseInputMonitorFactory before exercising the recorder."],"tags":["di","ioc","recording","dependency-injection","mouse"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}