{"record":{"id":"6f85cb4f8e160023","repo":"babalae/better-genshin-impact","slug":"raw-input","errorCode":null,"errorMessage":"Raw Input 初始化失败","messagePattern":"Raw Input 初始化失败","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Monitor/RawInputMonitor.cs","lineNumber":76,"sourceCode":"        }\n\n        if (!context.Initialized.Wait(InitializationTimeout))\n        {\n            ClearContext(context);\n            RequestStop(context);\n            throw new TimeoutException(\n                $\"Raw Input 采集线程初始化超过 {InitializationTimeout.TotalSeconds:0} 秒。\");\n        }\n        context.Initialized.Dispose();\n\n        if (context.InitializationException == null)\n        {\n            return;\n        }\n\n        ClearContext(context);\n\n        throw new InvalidOperationException(\"Raw Input 初始化失败\", context.InitializationException);\n    }\n\n    protected override void StopCore()\n    {\n        RawInputThreadContext? context;\n        long stopVersion;\n        lock (_sourceLock)\n        {\n            stopVersion = ++_lifecycleVersion;\n            context = _context;\n        }\n\n        if (context?.Dispatcher == null || context.Thread == null)\n        {\n            return;\n        }\n\n        if (Thread.CurrentThread == context.Thread)","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Monitor/RawInputMonitor.cs#L58-L94","documentation":"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.","triggerScenarios":"RegisterRawInputDevices failed on the worker thread; HwndSource creation threw; an exception occurred between AddHook and context.Initialized.Set() so InitializationSucceeded stayed false.","commonSituations":"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.","solutions":["Inspect ex.InnerException (or ex.GetBaseException()) for the real cause.","Confirm the app runs in an interactive desktop session, not a service/non-interactive context.","Fall back to DirectInput relative-mouse monitoring if Raw Input is unavailable.","Retry once; transient initialization races can succeed on a second attempt."],"exampleFix":"// before\nmonitor.Start();\n\n// after\ntry\n{\n    monitor.Start();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Raw Input 初始化失败\"))\n{\n    logger.LogError(ex.InnerException, \"RawInput 初始化失败，回退到 DirectInput\");\n    factory.Get(RelativeMouseInputType.DirectInput).Start();\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    monitor.Start();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Raw Input 初始化失败\"))\n{\n    logger.LogError(ex.InnerException, \"RawInput 不可用，回退 DirectInput\");\n    factory.Get(RelativeMouseInputType.DirectInput).Start();\n}","preventionTips":["Always log ex.InnerException to find the real cause.","Provide a DirectInput fallback for environments where Raw Input is unavailable.","Confirm an interactive desktop session before relying on Raw Input."],"tags":["rawinput","mouse","monitor","invalidoperation"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}