babalae/better-genshin-impact · error · Win32Exception

注册 Raw Input 鼠标设备失败

Error message

注册 Raw Input 鼠标设备失败

What it means

RegisterRawInputDevices (the Win32 API) returns false when registration fails; RawInputMonitor throws a Win32Exception built from Marshal.GetLastPInvokeError(). The device registered is the mouse with RIDEV_INPUTSINK (receive input even when not foreground) bound to the message-only HWND. Failure typically means the HWND target is invalid or the session disallows raw input.

Source

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

    private void RegisterRawInput(RawInputThreadContext context)
    {
        var devices = new[]
        {
            new User32.RAWINPUTDEVICE
            {
                usUsagePage = GenericDesktopUsagePage,
                usUsage = MouseUsage,
                dwFlags = User32.RIDEV.RIDEV_INPUTSINK,
                hwndTarget = context.HwndSource!.Handle
            }
        };

        if (!User32.RegisterRawInputDevices(
                devices,
                (uint)devices.Length,
                (uint)Marshal.SizeOf<User32.RAWINPUTDEVICE>()))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "注册 Raw Input 鼠标设备失败");
        }
    }

    private void CleanupContext(RawInputThreadContext context)
    {
        if (context.Registered)
        {
            var devices = new[]
            {
                new User32.RAWINPUTDEVICE
                {
                    usUsagePage = GenericDesktopUsagePage,
                    usUsage = MouseUsage,
                    dwFlags = User32.RIDEV.RIDEV_REMOVE,
                    hwndTarget = HWND.NULL
                }
            };

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Inspect the NativeErrorCode in the Win32Exception to map the exact Win32 failure.
  2. Ensure Start() is not racing with Stop()/Dispose() that destroys the HWND.
  3. Run in an interactive desktop session; fall back to DirectInput if unavailable.
  4. Retry registration after recreating the HWND.

Example fix

// before
monitor.Start();

// after
try
{
    monitor.Start();
}
catch (Win32Exception ex) when (ex.Message.Contains("注册 Raw Input 鼠标设备失败"))
{
    logger.LogError("RawInput 注册失败 Win32Error={Code}", ex.NativeErrorCode);
    throw;
}
Defensive patterns

Strategy: try-catch

Try / catch

try
{
    monitor.Start();
}
catch (System.ComponentModel.Win32Exception ex) when (ex.Message.Contains("注册 Raw Input 鼠标设备失败"))
{
    logger.LogError("RawInput 注册失败 Win32Error={Code}", ex.NativeErrorCode);
    // fall back to DirectInput if available
}

Prevention

When it happens

Trigger: context.HwndSource.Handle is zero/disposed at registration time; running in a non-interactive session; another process holds an incompatible raw-input registration; insufficient privileges for INPUTSINK.

Common situations: RDP/session transitions disposing the HWND; rapid Start/Stop where the HWND was torn down; headless/service hosting; security software blocking raw input.

Related errors


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