babalae/better-genshin-impact · error · InvalidOperationException

Raw Input 初始化失败

Error message

Raw Input 初始化失败

What it means

After the STA thread signals (or times out), RawInputMonitor checks context.InitializationException; if the worker captured an exception during setup (e.g. HWND creation, RegisterRawInputDevices), it wraps it in InvalidOperationException('Raw Input 初始化失败') and rethrows. This is the 'thread reported a failure' counterpart to the timeout path, preserving the original cause as InnerException.

Source

Thrown at BetterGenshinImpact/Core/Monitor/RawInputMonitor.cs:76

        }

        if (!context.Initialized.Wait(InitializationTimeout))
        {
            ClearContext(context);
            RequestStop(context);
            throw new TimeoutException(
                $"Raw Input 采集线程初始化超过 {InitializationTimeout.TotalSeconds:0} 秒。");
        }
        context.Initialized.Dispose();

        if (context.InitializationException == null)
        {
            return;
        }

        ClearContext(context);

        throw new InvalidOperationException("Raw Input 初始化失败", context.InitializationException);
    }

    protected override void StopCore()
    {
        RawInputThreadContext? context;
        long stopVersion;
        lock (_sourceLock)
        {
            stopVersion = ++_lifecycleVersion;
            context = _context;
        }

        if (context?.Dispatcher == null || context.Thread == null)
        {
            return;
        }

        if (Thread.CurrentThread == context.Thread)

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Inspect ex.InnerException (or ex.GetBaseException()) for the real cause.
  2. Confirm the app runs in an interactive desktop session, not a service/non-interactive context.
  3. Fall back to DirectInput relative-mouse monitoring if Raw Input is unavailable.
  4. Retry once; transient initialization races can succeed on a second attempt.

Example fix

// before
monitor.Start();

// after
try
{
    monitor.Start();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Raw Input 初始化失败"))
{
    logger.LogError(ex.InnerException, "RawInput 初始化失败,回退到 DirectInput");
    factory.Get(RelativeMouseInputType.DirectInput).Start();
}
Defensive patterns

Strategy: fallback

Try / catch

try
{
    monitor.Start();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Raw Input 初始化失败"))
{
    logger.LogError(ex.InnerException, "RawInput 不可用,回退 DirectInput");
    factory.Get(RelativeMouseInputType.DirectInput).Start();
}

Prevention

When it happens

Trigger: RegisterRawInputDevices failed on the worker thread; HwndSource creation threw; an exception occurred between AddHook and context.Initialized.Set() so InitializationSucceeded stayed false.

Common situations: Raw input unavailable in the session (remote desktop without raw-input passthrough); missing user32 support; the monitor stopped concurrently and the worker saw StopRequested and threw OperationCanceledException (error 31) which surfaces here too.

Related errors


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