剪贴板与环境信息
vscode.env 命名空间提供两类能力:与系统交互的工具(剪贴板、外部浏览器)和描述运行环境的元数据。前者让插件融入用户工作流,后者让插件在不同环境下做出正确行为。
剪贴板读写
env.clipboard 封装系统剪贴板,读写都是异步的:
typescript
// 写入
await vscode.env.clipboard.writeText('复制到系统剪贴板的内容');
// 读取
const text = await vscode.env.clipboard.readText();
console.log('剪贴板内容:', text);实用场景:把诊断结果复制出来
typescript
async function copyDiagnostics() {
const editor = vscode.window.activeTextEditor;
if (!editor) return;
// 收集当前文件的问题
const diagnostics = vscode.languages.getDiagnostics(editor.document.uri);
// 拼接成文本
const lines = diagnostics.map(d =>
`[${d.severity === vscode.DiagnosticSeverity.Error ? '错误' : '警告'}] ` +
`行 ${d.range.start.line + 1}: ${d.message}`
);
const text = `文件: ${editor.document.fileName}\n` + lines.join('\n');
// 写入剪贴板并提示
await vscode.env.clipboard.writeText(text);
vscode.window.showInformationMessage(
`已复制 ${diagnostics.length} 条诊断到剪贴板`
);
}剪贴板读写适用于复制文本到系统剪贴板,注意剪贴板内容会覆盖用户之前的复制内容,写前最好先确认用户意图。
环境信息一览
env 暴露运行环境的只读信息:
| 属性 | 类型 | 含义与典型值 |
|---|---|---|
appName | string | 产品名,如 Visual Studio Code |
appHost | string | 宿主平台,desktop / web / ssh / codespaces |
appRoot | string | VSCode 安装目录(只读,勿写入) |
language | string | 界面语言,如 zh-cn、en |
shell | string | 默认终端 shell 路径 |
sessionId | string | 当前会话 ID(进程级唯一) |
machineId | string | 本机唯一标识(已匿名化) |
remoteName | string | 远程类型,如 ssh-remote;本地为空字符串 |
uriScheme | string | 链接协议,vscode 或 vscode-insiders |
platform | string | 操作系统:win32 / darwin / linux |
isNewAppInstall | boolean | 是否新安装的应用 |
isTelemetryEnabled | boolean | 用户是否开启遥测 |
typescript
function reportEnvironment() {
console.log('产品:', vscode.env.appName);
console.log('宿主:', vscode.env.appHost);
console.log('语言:', vscode.env.language);
console.log('远程:', vscode.env.remoteName || '本地');
console.log('协议:', vscode.env.uriScheme);
console.log('平台:', vscode.env.platform);
}appRoot 与 platform 判断
appRoot 指向 VSCode 安装目录,可用于读取 VSCode 自带的资源;platform 用于分支处理平台差异:
typescript
import * as path from 'path';
// 读取安装目录下的静态资源
const root = vscode.env.appRoot;
const licenseFile = path.join(root, 'LICENSE.txt');
// 平台分支:不同系统使用不同的默认 shell
function defaultShellForPlatform(): string {
switch (vscode.env.platform) {
case 'win32': return 'powershell.exe';
case 'darwin': return '/bin/zsh';
default: return '/bin/bash';
}
}appRoot 在远程/Web 环境语义不同:远程开发时指向远程端的安装目录,Web 版可能为空或指向打包资源,读取安装目录文件前应做存在性检查。
用 sessionId 区分实例
多个 VSCode 窗口共享扩展进程时,sessionId 可用于标记插件状态归属:
typescript
// 每次会话唯一的标识,适合作为临时缓存键
const cacheKey = `myext.cache.${vscode.env.sessionId}`;
// 会话结束后自动清理
vscode.workspace.workspaceState.update(cacheKey, undefined);openExternal 打开外部链接
env.openExternal 用系统默认程序打开 URI,支持多种协议:
typescript
// 1. 打开网页
await vscode.env.openExternal(vscode.Uri.parse('https://example.com'));
// 2. 打开邮件客户端
await vscode.env.openExternal(vscode.Uri.parse('mailto:support@example.com'));
// 3. 唤起本机其他应用(如打开文件管理器)
await vscode.env.openExternal(vscode.Uri.file('/workspace'));
// 4. 打开 vscode 协议链接(如扩展商店搜索)
await vscode.env.openExternal(
vscode.Uri.parse('vscode:extension/github.copilot')
);注意事项
- 只接受
http、https、mailto等安全协议,vscode.Uri.file也会被映射到系统文件打开方式 - 打开前校验用户输入,避免把用户内容拼进 URL 后直接打开
- 在 Web 版(
appHost === 'web')中行为略有差异,仍会尝试新窗口打开
安全校验示例
typescript
async function openUserProvidedUrl(raw: string) {
try {
const uri = vscode.Uri.parse(raw);
// 只允许 https,防止协议注入
if (uri.scheme !== 'https' && uri.scheme !== 'http') {
vscode.window.showWarningMessage('仅支持 http/https 链接');
return;
}
await vscode.env.openExternal(uri);
} catch {
vscode.window.showErrorMessage('无效的链接');
}
}asExternalUri 转换内部 URI
某些 URI(如 Webview 的本地资源、调试会话地址)只能在 VSCode 内部使用。asExternalUri 把内部 URI 转为浏览器可访问的外部链接:
typescript
// 把 Webview 的本地静态资源转为外部 URL
const internalUri = vscode.Uri.parse(
'vscode-webview-resource://myext/resources/index.html'
);
const externalUri = await vscode.env.asExternalUri(internalUri);
console.log('浏览器可访问:', externalUri.toString());
// 或创建一条可分享的链接(如 http/https 或自定义协议)
const shareable = await vscode.env.asExternalUri(
vscode.Uri.parse('https://localhost:8080/callback')
);典型用途:Webview 中需要把本地文件交给外部工具处理时,先把 vscode-webview-resource URI 转成 http(s)://127.0.0.1:端口/... 形式,再在 Webview 内引用。
实战:环境诊断命令
把这些 API 组合成一条"环境信息复制"命令:
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('myext.copyEnvInfo', async () => {
const lines = [
`应用名称: ${vscode.env.appName}`,
`版本: ${vscode.version}`,
`宿主: ${vscode.env.appHost}`,
`平台: ${vscode.env.platform}`,
`语言: ${vscode.env.language}`,
`远程: ${vscode.env.remoteName || '本地'}`,
`协议: ${vscode.env.uriScheme}`,
`安装目录: ${vscode.env.appRoot}`,
`默认 Shell: ${vscode.env.shell}`,
`会话 ID: ${vscode.env.sessionId}`
];
await vscode.env.clipboard.writeText(lines.join('\n'));
vscode.window.showInformationMessage('环境信息已复制到剪贴板');
// 顺带打开文档站
await vscode.env.openExternal(
vscode.Uri.parse('https://code.visualstudio.com/api')
);
})
);
// 平台相关的菜单/设置适配
const isWindows = vscode.env.platform === 'win32';
vscode.commands.executeCommand('setContext', 'myext.isWindows', isWindows);
}剪贴板打通了插件与系统交互的最后一公里,环境信息则提供了运行时判断的依据。二者结合,插件可以写出"复制环境诊断信息"这类小而实用的功能,也能在 Web、远程、桌面三种形态下各自适配。