
1. 先搞清楚 Run Code 在背后到底干了什么Code Runner 这个插件在 VSCode 装机量里常年排在前列很多人第一次接触 VSCode 的插件生态就是从它开始的。它的价值在于把编译 运行 看输出这条链路压成一次点击但它同时也是一个典型的配置驱动型插件——你给它什么配置它就执行什么命令中间不做任何智能纠错。所以搞清楚它的运行机制和配置文件结构比死记几个快捷键有用得多。我先说清楚它能做什么对单个源文件它可以按语言类型自动拼出一条命令行调起你本机已经装好的编译器或解释器gcc、g、python、node、go、javac 等等把结果回显到 VSCode 的输出面板或者集成终端里。它不负责安装环境不负责解析依赖不负责生成构建脚本。这一点非常重要新手最常见的误解就是我装了 Code Runner 就能跑 C 了实际上编译器和环境变量还是得自己配好插件只负责替你敲那行命令。适合谁来参考这篇文章刚装好 VSCode 想跑第一个 Hello World 的新手、写了几年脚本但一直没细看 settings.json 里那堆 code-runner.* 配置项的人以及被中文乱码找不到主类选中代码运行读不到文件这类问题折腾过的同学。下面我按机制 → 映射表 → 配置项 → 改造实例 → 排错的顺序展开读完你基本能自己写一套专属的 executorMap。2. 一次点击触发的完整链路2.1 从按下快捷键到看见执行时间整个流程拆开大概是这样几段我按实际发生顺序讲入口触发编辑器右上角的三角图标、编辑器右键菜单里的 Run Code、快捷键 CtrlAltNMac 是 CtrlOptionN这三者走的是同一条命令code-runner.run。命令面板里输入 Run Code 也是同一个。保存判定插件先检查saveFileBeforeRun和saveAllFilesBeforeRun。这两个默认都是 false也就是说默认状态下它运行的是磁盘上最后一次保存的内容不是你编辑器里正在敲的内容。我见过有人改了代码没保存运行结果对不上纠结半天——就是这个原因。选区判定如果编辑器里有选中文本且ignoreSelection为 false插件会走只跑选中部分的逻辑把选中内容写进一个临时文件再执行这一步后面单独讲。匹配执行器根据文件的 languageId 或扩展名去executorMapByGlob、executorMapByFileExtension、executorMap三级映射里查表命中第一条。都不命中就看 shebangrespectShebang默认开启再不行就退化到defaultLanguage。变量替换把命令模板里的$dir、$fileName、$fileNameWithoutExt这类占位符替换成真实值拼成最终的可执行命令字符串。选择执行环境由runInTerminal决定走集成终端还是走内部输出面板Code 这个 Output Channel。回显结果把 stdout、stderr 写出来末尾附一句类似「执行时间: 132 ms」的提示这条提示由showExecutionMessage控制。2.2 输出面板模式和终端模式选错了会很别扭runInTerminal这个开关的默认值是 false也就是默认走输出面板。两种模式的差别不是好看不好看而是能不能交互。输出面板模式的优点是干净、快、没有 shell 提示符和上次运行的残留输出混在一起适合跑一次看个结果的场景。它的硬伤是不接 stdin程序里写了input()或者scanf光标就在那儿等着你没有任何地方可以输入只能点停止。另外它不走登录 shell环境变量会比你在终端里手敲少一些。终端模式设成 true就是把拼好的命令直接丢进 VSCode 的集成终端执行支持输入、支持颜色、支持各种需要 TTY 的程序。缺点是同一个终端窗口会被反复复用上一条命令的回显还在输出容易乱。这时候可以配合clearPreviousOutput和preserveFocus一起用preserveFocus保持焦点留在编辑器不至于跑一次就跳走clearPreviousOutput在每次运行前清屏让输出面板干净一点。我的习惯是写算法题、跑单元测试那种一次性脚本用输出面板写需要交互输入的练习程序、或者要长时间跑的服务就在工作区级别把runInTerminal打开。3. executorMap整个插件真正的核心3.1 三级映射的优先级顺序这是配置文件里最容易搞混的部分。插件查表的顺序是固定的优先级配置项匹配依据典型用途1code-runner.executorMapByGlob文件路径 glob如*.test.js测试文件、模板文件单独走一套命令2code-runner.executorMapByFileExtension文件扩展名如.ts、.luau同一语言不同后缀走不同工具链3code-runner.executorMapVSCode 的 languageId如cpp、python主力配置90% 的人只改这一层4shebang文件首行的#!脚本文件指定解释器5code-runner.defaultLanguage兜底默认javascript注意executorMapByGlob和executorMapByFileExtension是后来版本才加的如果你用的是很老的版本这两个键写了也不生效先确认插件版本。优先级顺序意味着一个坑如果你在executorMap里给javascript配了node又在executorMapByGlob里配了*.test.js走别的命令那所有.test.js文件都会走第二条不看第一条。排查配置明明改了却不生效的时候先按这个表从下往上找。3.2 变量占位符清单写自定义命令全靠它命令模板里的变量是这套机制的灵魂没有它们executorMap就只能写死绝对路径。常用的我整理成表变量含义示例文件D:/proj/src/main.cpp$workspaceRoot工作区根目录D:/proj$dir当前文件所在目录带结尾斜杠D:/proj/src/$dirWithoutTrailingSlash同上去掉结尾斜杠D:/proj/src$fullFileName完整路径D:/proj/src/main.cpp$fileName文件名带后缀main.cpp$fileNameWithoutExt文件名不带后缀main$fileExtname扩展名.cpp$fileDirname文件所在目录名src$relativeFileDirname相对工作区的目录src$pythonPathPython 解释器路径取自 Python 插件配置$line/$column光标行列号12/4$selectedText当前选中文本整段选中的代码$pythonPath是个特殊变量它不来自当前文件而是读取 Python 扩展配置里的解释器路径。这就是为什么切换虚拟环境之后用 Code Runner 跑 Python 会自动用上新解释器——前提是你装了 Python 扩展并且解释器是通过官方方式选的。3.3 我自己长期在用的几套映射官方默认的 C/C 命令在 Windows 上经常出问题因为它把可执行文件输出到$dir$fileNameWithoutExt路径里有空格就挂。我自己的版本是这样code-runner.executorMap: { c: cd $dir gcc \$fileName\ -o \$fileNameWithoutExt.exe\ \$dir$fileNameWithoutExt.exe\, cpp: cd $dir g \$fileName\ -o \$fileNameWithoutExt.exe\ -stdc17 -Wall \$dir$fileNameWithoutExt.exe\, python: python -u, java: cd $dir javac -encoding UTF-8 \$fileName\ java -Dfile.encodingUTF-8 $fileNameWithoutExt, go: cd $dir go run \$fileName\, javascript: node, typescript: cd $dir npx ts-node \$fileName\ }几个改动点值得说明给文件名和输出路径都加双引号是为了对付带空格的项目目录g后面加-stdc17 -Wall是因为默认标准太老写现代 C 语法会莫名其妙报错而且开-Wall能提前抓出一堆低级问题Python 后面跟的-u是关闭输出缓冲不加的话print的内容会攒着一起吐出来调试循环体的时候非常难受。Java 那条加了-encoding UTF-8不加的话在中文环境下编译含中文注释的源文件会报编码错误。这是 Windows 上 Java 的老毛病源文件是 UTF-8 但编译器默认按系统编码读两边对不上。4. settings.json 里那些容易被忽略的开关4.1 决定跑的是哪一版代码的几个键saveFileBeforeRun和saveAllFilesBeforeRun这两个默认关闭我强烈建议至少打开第一个。原因很简单你在编辑器里改了三行按 CtrlAltN 看到的是旧结果然后开始怀疑人生。打开之后每次运行自动保存当前文件行为符合直觉。saveAllFilesBeforeRun更激进会保存整个工作区的所有脏文件多文件项目里比较实用代价是偶尔会触发一些自动格式化类的保存钩子。ignoreSelection默认 false意思是有选中就跑选中。这个默认值坑过不少人随手选了一段代码想按 CtrlC结果手滑按成 CtrlAltN跑出来的结果是半截代码的报错。如果你从来不使用选区运行功能直接把它设成 true选区会被忽略永远跑整个文件。stopOnError默认 true指的是保存文件或生成临时文件这一步出错就中止不是指编译报错就停。它跟程序本身的退出码没关系。4.2 工作目录相对路径报错八成出在这儿fileDirectoryAsCwd默认 falsecwd默认为空。两个都不设的时候工作目录是什么在终端模式下基本等于工作区根目录在输出面板模式下取决于调用方式。这就导致一个非常常见的现象代码里写open(data.txt)在终端手敲能跑通用 Code Runner 跑就FileNotFoundError。解决办法有两个。一是把fileDirectoryAsCwd设成 true让执行目录始终跟着当前文件走这样data.txt和源文件同级就能读到。二是在命令模板里显式cd $dir 效果一样而且在同一个工作区里对不同语言可以分别控制。提示cd $dir 这种写法在 Windows 上也能用cd加正斜杠路径 VSCode 传给 shell 之后能正确解析。但如果是 PowerShell 作为默认 shell某些带特殊字符的目录名仍可能出问题所以路径变量外面套双引号是个好习惯。4.3 输出表现和遥测开关showExecutionMessage控制那句「执行时间」提示默认 true。嫌它碍事或者输出要被程序解析的话关掉更干净。clearPreviousOutput默认 false配合输出面板使用效果最好每次运行先清空上一次的内容。enableAppInsights是使用数据上报开关默认 true如果工作环境对这类上报有要求可以关掉不影响任何功能。respectShebang默认 true对于带#!/usr/bin/env python3的脚本文件即使executorMap里配了别的解释器也会优先按 shebang 走。想让映射表说话就把它关掉。5. 几个改造实例直接抄作业5.1 C/C 多文件编译怎么处理Code Runner 天然只认单文件$fileName只代表当前这一个文件。你要编译三个.cpp文件默认映射搞不定。常见的做法是在executorMapByGlob里给特定后缀配一条命令或者干脆在项目里放一个Makefile然后把映射改成调用 makecode-runner.executorMapByGlob: { *.cpp: cd $dir g *.cpp -o $fileNameWithoutExt.exe -stdc17 \$dir$fileNameWithoutExt.exe\ }这条命令里的*.cpp交给 shell 展开会把这个目录下所有源文件一起编译。优点是简单粗暴缺点是文件一多就会混进main函数冲突而且每次全量重编。项目稍大一点就应该换成make或cmake --build build把构建逻辑交给专业工具Code Runner 只当个触发器。这个思路值得记住插件负责触发构建工具负责正确性。5.2 Python 指定解释器和虚拟环境Python 的场景更绕一点因为解释器可能来自虚拟环境、conda、或者系统自带。默认映射写的是python -u这个python是走 PATH 找的。如果你的虚拟环境没激活PATH 里就是系统那个。最省事的做法是把映射改成读$pythonPathcode-runner.executorMap: { python: $pythonPath -u $fullFileName }这样解释器跟着 Python 扩展的选择走在左下角点一下切换解释器Code Runner 立刻用新的不用改配置。注意$pythonPath只在装了 Python 扩展时才有值纯编辑器环境下这个变量是空的命令会变成-u xxx.py直接报错。所以要么装扩展要么老老实实写死路径。另一个高频问题是模块导入。代码里写from utils import foo用 Code Runner 一跑就ModuleNotFoundError。原因是执行目录不对sys.path[0]变成了源文件所在目录之外的地方。把fileDirectoryAsCwd打开或者在命令前加cd $dir 一般能解决。5.3 选中代码运行的临时文件机制这个机制值得单独说因为它解释了一大堆灵异现象。当你有选中文本并运行插件会把选中的内容写到一个临时文件里文件名类似tempCodeRunnerFile.py放在系统临时目录然后执行这个临时文件。你甚至可以在这个临时文件里下断点调试。由此带来的副作用有两个。第一临时文件在系统临时目录不在你的项目目录所以代码里所有相对路径都失效了工作目录变成了临时目录或工作区根目录。第二某些系统清理工具会在运行过程中把临时目录里的文件删掉导致偶尔出现文件不存在的报错。理解了这两点遇到这类报错就不用乱猜了。还有个隐藏的坑临时文件的扩展名是根据 languageId 推出来的。如果你用的是某个自定义语言、又没配languageIdAsFileExtension扩展名可能生成得不对脚本解释器认不出来。6. 常见问题速查与排查思路6.1 问题对照表现象大概率原因处理方式改了代码结果没变没自动保存开saveFileBeforeRun中文输出乱码编码不匹配常见于 Windows 控制台Java 加-encoding UTF-8PowerShell 里先设chcp 65001找不到文件 / 相对路径失效工作目录不对开fileDirectoryAsCwd或命令里加cd $dir 路径含空格报错命令里变量没加引号给$fileName、输出路径套上双引号编译通过但找不到可执行文件输出路径拼接错检查$dir$fileNameWithoutExt是否和-o一致改了 executorMap 不生效被更高优先级映射或 shebang 覆盖依次检查 Glob 映射、扩展名映射、respectShebang程序卡住不动等输入输出面板不支持 stdin打开runInTerminalPowerShell 报执行策略错误系统脚本执行策略限制改用 cmd 作为默认终端或调整策略快捷键没反应与其他插件冲突打开键盘快捷方式搜索code-runner.run重新绑定终端里命令被执行两次终端复用 命令拼接问题开clearPreviousOutput或换个终端 profile6.2 编码和权限类问题的处理顺序中文乱码这个事我踩了很多次之后总结出一个排查顺序先确认源文件本身是 UTF-8 保存的VSCode 右下角能看到编码再看编译或解释时有没有指定编码参数最后看终端自身的编码设置。三层里任何一层不对都会乱码而且现象长得都一样所以必须按顺序验。Windows 上还有个独立的坑是 PowerShell 的执行策略某些默认配置下不允许执行本地脚本会直接拒绝运行。遇到这种报错不用去改系统设置直接把 VSCode 的默认终端 profile 换成 Command Prompt最快的解法。6.3 和其他 VSCode 插件共存时的冲突现在很多人的 VSCode 里同时装了三五个插件冲突是常态。最容易撞车的是快捷键AI 编程助手类插件、终端类插件、笔记类插件都爱抢 CtrlAltN、CtrlAltM 这类组合表现就是按下去毫无反应或者弹出了别的面板。排查方法很直接CtrlShiftP 打开命令面板搜 Run Code如果命令能执行那就是快捷键被占了去键盘快捷方式里改一个就行。另一类是输出通道冲突。有些插件也会创建一个叫 Code 的输出面板或者往同一个终端里写东西导致你看到的输出混着两边的日志。这时候可以把runInTerminal切一下模式换个通道观察很快就能定位是哪边在捣乱。还有一类不太明显的是保存钩子冲突。你开了saveAllFilesBeforeRun运行前会触发全量保存如果工作区里有自动格式化、自动修复类的插件保存瞬间可能改动文件内容导致你运行的代码和你看到的不完全一样。排查这类问题时可以临时把自动格式化关掉对比一次。7. 我最后想补充的几点体会这套配置体系其实就三层映射表决定跑什么命令变量决定命令里的路径对不对开关决定在什么环境里跑。绝大多数问题都落在第二层。你把$dir、$fileName、$fileNameWithoutExt三个变量的实际值在心里默念一遍拼成完整命令然后复制到系统终端里手敲一次能不能跑通一目了然。这个手动复现一遍的动作我用它定位过八成以上的 Code Runner 问题。还有一个习惯上的建议把executorMap写在工作区级别的settings.json项目根目录.vscode/settings.json里而不是全局。不同项目的编译参数、标准版本、编码要求经常不一样写全局会互相干扰写工作区还能跟着 Git 走换台机器直接就有。全局那份只留最通用的一两条比如saveFileBeforeRun、fileDirectoryAsCwd这种和项目无关的行为开关。这套东西平时看着繁琐但一旦按你的习惯配好它就是 VSCode 里最高频的按钮之一。我现在写单文件脚本、验证某个语法、跑一段临时逻辑基本都是 CtrlAltN 解决连开终端的动作都省了。花半个小时把executorMap调顺手后面省下的时间远不止半个小时。