babalae/better-genshin-impact · error · InvalidOperationException

相对鼠标捕获工厂未注册

Error message

相对鼠标捕获工厂未注册

What it means

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.

Source

Thrown at BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs:75

        try
        {
            SystemControl.ActivateWindow();

            _logger.LogInformation("录制:{Text}", "实时任务已暂停");
            _logger.LogInformation("注意:录制时遇到主界面(鼠标永远在界面中心)和其他界面(鼠标可自由移动,比如地图等)的切换,请把手离开鼠标等待录制模式切换日志");

            for (var i = 3; i >= 1; i--)
            {
                _logger.LogInformation("{Sec}秒后启动录制...", i);
                await Task.Delay(1000);
            }

            TaskTriggerDispatcher.Instance().StopTimer();
            taskTriggerStopped = true;

            _recorder = new KeyMouseRecorder();
            var monitorFactory = App.GetService<IRelativeMouseInputMonitorFactory>()
                                 ?? throw new InvalidOperationException("相对鼠标捕获工厂未注册");
            _relativeMouseSubscription = monitorFactory
                .Get(inputType)
                .Subscribe(RelativeMouseMoved);

            _timer.Start();
            Status = KeyMouseRecorderStatus.Recording;

            _logger.LogInformation("录制:已启动,相对鼠标捕获方式:{InputType}", inputType);
            return true;
        }
        catch (Exception ex)
        {
            _timer.Stop();
            try
            {
                _relativeMouseSubscription?.Dispose();
            }
            catch (Exception disposeException)

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Ensure App.xaml.cs registers services.AddSingleton<IRelativeMouseInputMonitorFactory, RelativeMouseInputMonitorFactory>().
  2. Only call StartRecord after the application DI container is initialized (e.g. after the startup page loads).
  3. In tests, register a mock IRelativeMouseInputMonitorFactory before exercising StartRecord.
  4. Guard the call with App.GetService(...) != null and warn the user instead of throwing.

Example fix

// before
var monitorFactory = App.GetService<IRelativeMouseInputMonitorFactory>()
    ?? throw new InvalidOperationException("相对鼠标捕获工厂未注册");

// after: graceful user-facing error
var monitorFactory = App.GetService<IRelativeMouseInputMonitorFactory>();
if (monitorFactory == null)
{
    await ThemedMessageBox.ErrorAsync("录制组件未就绪,请稍后重试", "键鼠录制启动失败");
    return false;
}
Defensive patterns

Strategy: validation

Validate before calling

var factory = App.GetService<IRelativeMouseInputMonitorFactory>();
if (factory is null)
{
    await ThemedMessageBox.ErrorAsync("录制组件未就绪,请稍后重试", "键鼠录制启动失败");
    return false;
}
// then proceed with factory.Get(inputType)

Try / catch

try { return await StartRecord(inputType); }
catch (InvalidOperationException ex) when (ex.Message.Contains("相对鼠标捕获工厂未注册"))
{ _logger.LogError(ex, "DI not ready for recording."); await ThemedMessageBox.ErrorAsync(ex.Message, "键鼠录制启动失败"); return false; }

Prevention

When it happens

Trigger: Calling GlobalKeyMouseRecord.Instance.StartRecord(...) before App startup completes the DI registration, or running in a test/host that never registered IRelativeMouseInputMonitorFactory.

Common situations: 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.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/a89657958a7dbf93. Report an issue: GitHub.