{"record":{"id":"36e09c346eb08a2a","repo":"babalae/better-genshin-impact","slug":"session","errorCode":null,"errorMessage":"无法取得命名管道客户端的进程或 Session 信息。","messagePattern":"无法取得命名管道客户端的进程或 Session 信息。","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Service/Instance/MessageHandlers/InstanceRequestHandler.cs","lineNumber":150,"sourceCode":"    /// v2 不再校验父实例 ID 或启动记录，而是使用根管道客户端的真实 PID 和 Session。\n    /// </summary>\n    private async Task<InstanceIpcEnvelope> HandleConnectionOpenAsync(\n        InstanceConnection connection,\n        InstanceIpcEnvelope request,\n        CancellationToken cancellationToken)\n    {\n        if (_context.InstanceType != BetterGiInstanceType.Primary)\n        {\n            throw new InvalidOperationException(\"只有根实例可以接受客户端连接登记。\");\n        }\n        if (connection.RemoteEndpoint is not null)\n        {\n            throw new InvalidOperationException(\"当前管道连接已经完成登记。\");\n        }\n        if (connection.ClientProcessId is not { } processId\n            || connection.ClientSessionId is not { } sessionId)\n        {\n            throw new InvalidOperationException(\"无法取得命名管道客户端的进程或 Session 信息。\");\n        }\n\n        var open =\n            request.Data?.ToObject<ConnectionOpenRequest>(InstanceIpcProtocol.Serializer)\n            ?? throw new ArgumentException(\"连接登记请求缺少数据。\");\n        if (open.RequestedType == BetterGiInstanceType.WebView)\n        {\n            var endpoint = CreateEndpoint(\n                BetterGiInstanceType.WebView,\n                processId,\n                sessionId);\n            connection.RemoteEndpoint = endpoint;\n            RegisteredInstanceConnection? replaced = null;\n            lock (_state.RegistrationLock)\n            {\n                if (_state.WebViewConnectionsByProcessId.TryGetValue(\n                        processId,\n                        out var existing)","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Service/Instance/MessageHandlers/InstanceRequestHandler.cs#L132-L168","documentation":"Thrown by HandleConnectionOpenAsync when either connection.ClientProcessId or connection.ClientSessionId is null. These are populated in the InstanceConnection constructor via native interop: GetNamedPipeClientProcessId and ProcessIdToSessionId (kernel32.dll) called on the server-side pipe's SafePipeHandle. If the native call fails (returns false), both remain null and the connection cannot be registered because the root needs the client's PID and Windows Session ID for routing and authorization.","triggerScenarios":"The root's InstanceConnection constructor receives a NamedPipeServerStream but InstancePipePeerInfo.TryGetClientProcessAndSession fails. GetNamedPipeClientProcessId can fail if the pipe handle is invalid, if the client has already disconnected before the server reads peer info, or if the OS denies the information query. ProcessIdToSessionId can fail if the process has exited.","commonSituations":"The client process connected and immediately disconnected (crash, force-kill) before the server could query its PID; running under a constrained security context where GetNamedPipeClientProcessId is denied; a Windows version or configuration that does not support this native API; an anonymized pipe where client identity is not available; the pipe handle was disposed before the constructor ran.","solutions":["Ensure the client process stays alive long enough for the server to query its PID — if the client crashes on startup, fix the crash.","Verify the named pipe is created with PIPE_TYPE_MESSAGE and proper security attributes (InstancePipeFactory.CreateServer) so client identity is queryable.","Check the SetLastError code from GetNamedPipeClientProcessId if it returns false — log it in InstancePipePeerInfo for diagnostics.","If this occurs in a specific Windows environment (e.g., Server Core, container), verify kernel32 pipe info APIs are available.","Handle gracefully by returning a Failure response to the client rather than throwing, so the client can retry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// After accepting a connection, verify peer info is available before proceeding\nif (connection.ClientProcessId is null || connection.ClientSessionId is null)\n{\n    _logger.LogWarning(\"无法获取管道客户端进程信息，关闭连接\");\n    await connection.DisposeAsync();\n    return;\n}","typeGuard":null,"tryCatchPattern":"// In HandleConnectionOpenAsync, this throws InvalidOperationException\n// which is caught by HandleAsync's catch block and returned as a Failure response:\ncatch (Exception exception) when (exception is ArgumentException\n    or InvalidOperationException or IOException or TimeoutException or JsonException)\n{\n    return InstanceIpcEnvelope.Failure(request, \"invalid_request\", exception.Message);\n}","preventionTips":["Ensure clients stay alive long enough for the server to query their PID.","Verify InstancePipeFactory.CreateServer creates pipes with proper attributes for peer info queries.","Log the Win32 error code from GetNamedPipeClientProcessId when it fails.","Return a Failure response instead of throwing for a more graceful client experience."],"tags":["ipc","named-pipe","native-interop","process-identity","windows-api"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}