VS Code LSP客户端如何通过命名管道连接C#调试态自研语言服务器
解决方案
最简VS Code LSP客户端(Node侧)配置
你不需要编写复杂的Node逻辑,只需要在VS Code插件的extension.ts中使用如下配置,即可直接连接已启动的LSP服务端,无需客户端负责启动服务进程:
import * as vscode from 'vscode'; import { LanguageClient, TransportKind } from 'vscode-languageclient/node'; let client: LanguageClient; export function activate(context: vscode.ExtensionContext) { client = new LanguageClient( 'custom-lsp', // 自定义LSP的唯一ID '自定义语言服务', // 展示用的LSP名称 // 传输配置核心部分 { transport: { kind: TransportKind.pipe, pipeName: 'LSP_Pipe' // 与你C#服务端的管道名保持一致 } }, // 客户端基础配置 { // 替换为你要关联的文件语言类型 documentSelector: [{ scheme: 'file', language: 'plaintext' }], synchronize: { fileEvents: vscode.workspace.createFileSystemWatcher('**/*') } } ); // 启动客户端发起连接 client.start(); } export function deactivate(): Thenable<void> | undefined { return client?.stop(); }
如果是首次创建VS Code插件项目,使用yo code生成默认的TS扩展模板,替换extension.ts内容后,在package.json的依赖项中添加"vscode-languageclient": "^9.0.0",执行npm install即可完成环境准备。
修正C#服务端的命名管道逻辑
你当前的服务端代码使用了两个NamedPipeClientStream主动连接管道,逻辑完全倒置:LSP服务端应当作为命名管道的服务端,等待VS Code客户端主动连接,同时命名管道本身支持双向读写,不需要拆分读写两个流,修正后的启动逻辑如下:
public async Task Start() { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .CreateLogger(); var pipeName = "LSP_Pipe"; // 用服务端流监听管道,双向传输 var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1); Log.Information("等待VS Code客户端连接..."); await pipeServer.WaitForConnectionAsync(); Log.Information("客户端已连接,RPC启动监听"); RPC = new JsonRpc(pipeServer, pipeServer, this); RPC.StartListening(); this.RPC.Disconnected += RPC_Disconnected; await Task.Delay(-1); }
调试操作步骤
- 先启动C# LSP服务端,看到等待连接的日志后再进行下一步
- 按F5启动VS Code插件调试窗口,打开对应后缀的代码文件,客户端会自动发起连接,触发
Initialize请求,即可看到服务端的初始化日志。
可选:使用TCP传输(更适合调试)
如果遇到命名管道权限问题,推荐优先用TCP做开发阶段的传输,配置更简单、跨平台兼容性更好:
- 客户端传输配置改为:
transport: { kind: TransportKind.socket, port: 8888 // 自定义未被占用的端口 }
- C#服务端改用
TcpListener监听对应端口,拿到双向流后传给JsonRpc即可。
内容的提问来源于stack exchange,提问作者Axelly
相关产品推荐
相关产品推荐

