ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WSL2 报错 HCS_E_HYPERV_NOT_INSTALLED 修复指南

WSL2 报错 HCS_E_HYPERV_NOT_INSTALLED 修复指南 在 Windows 上折腾 WSL2 的人迟早会撞上这行红字Error code: Wsl/Service/CreateVm/HCS/HCS_E_HYPERV_NOT_INSTALLED。它最让人抓狂的地方在于——命令行是你昨天还在用的那条发行版也是昨天还跑得好好的某次重启、某次系统更新、或者某个装完就忘的软件就把 WSL2 直接干趴下了。更迷惑的是wsl --install明明提示成功、控制面板里适用于 Linux 的 Windows 子系统也打着勾它就是说 hypervisor 没装。这篇东西我按自己的排查顺序来写先讲清楚这个报错到底在抱怨什么再给一套五分钟定性流程然后按功能位缺失 / hypervisor 未启动 / 固件没开 / 嵌套环境四条路径分别给方案。适合已经装了 WSL2 但突然起不来的人也适合刚买机器、第一次装 WSL2 直接撞墙的新手。全程只讲 Windows 本机侧的配置不涉及任何外部环境。1. 先把报错翻译成人话WSL2 到底在跟谁要资源1.1 为什么 WSL1 从来不出这个错WSL2 一装就崩理解这个报错得先接受一个事实WSL1 和 WSL2 是两套完全不同的东西只是共用了wsl.exe这个入口。WSL1 走的是系统调用翻译路线。你在里面跑ls、gcc、python实际执行的是被翻译后的 Windows 系统调用中间靠的是一个内核驱动lxcore.sys/lxss.sys。整条链路里没有任何虚拟化所以 WSL1 在一台 BIOS 里虚拟化开关关着的机器上照样能跑。WSL2 就完全是另一回事了。它是一个跑在轻量级虚拟机里的真 Linux 内核微软管这个虚拟机叫 Utility VM。这个 VM 由 Windows 的虚拟化栈直接创建内存是动态分配的启动只要一两秒所以你平时感觉不到它是台虚拟机。但它的本质就是虚拟机创建流程必须经过 hypervisor。这就是关键WSL2 依赖 hypervisor 处于运行状态。注意是运行状态不是功能已安装。这两者的差别就是 90% 的人卡在这里的原因。1.2 HCS 是谁HCS_E_HYPERV_NOT_INSTALLED 到底在抱怨什么Wsl/Service/CreateVm这一段说明报错发生在创建虚拟机这个阶段HCS是 Host Compute Service 的缩写对应系统里的服务名是vmcompute.exe。HCS 是 Windows 上创建和管理轻量级虚拟机的公共组件并不是 WSL 专用的。你在 Windows 上能想到的这些东西全都走 HCS容器Windows Container、Windows 沙盒Windows Sandbox、Windows Defender 应用程序防护以及我们的 WSL2。所以 HCS 出问题往往是一串东西一起出问题。WSL2 的调用链大致是这样wsl.exe把请求交给 WSL 服务WSL 服务调用 HCS要求创建一台 Utility VMHCS 检查当前的虚拟化栈hypervisor 加载了吗CPU 的虚拟化扩展可用吗任何一项不满足HCS 就返回HCS_E_HYPERV_NOT_INSTALLED。这里有个特别容易被误导的点报错字符串里的 NOT_INSTALLED 是历史遗留的措辞它并不严格等于Hyper-V 功能没装。在绝大多数实际案例里功能是装了的只是 hypervisor 没有真正被加载起来。我见过太多人一看到 NOT_INSTALLED 就反复执行dism启用功能启用完还是同样的错然后开始怀疑人生。真正需要拆开看的状态有三种功能位压根没启用功能位启用了但没重启功能位启用了、也重启了但 hypervisor 仍然没加载。第三种最隐蔽也最费时间。1.3 三种典型触发场景先对号入座我把遇到过的案例归成三类你可以先判断自己属于哪一类后面的方案能省不少时间。场景典型特征主要原因全新机器首次装 WSL2wsl --install提示成功装完发行版起不来功能位没启用或者启用后没重启用了一段时间突然挂掉昨天还好好的今天开机就报错hypervisorlaunchtype被改或系统更新后驱动冲突在虚拟机 / 云主机里用各种方法都试过永远卡在这一步宿主没开嵌套虚拟化或机型本身不支持第一类和第三类的排查思路差别很大。第一类是缺东西补上就行第三类是宿主不给本机怎么改都没用得去宿主那边动手。很多人把第三类当成第一类治折腾一整天毫无进展这就是方向错了。2. 别急着改配置五分钟定性是功能缺失、hypervisor 未启动还是固件没开2.1 用三条命令把状态一次看全我习惯先不动任何配置只读状态。三组命令就够。第一组看任务管理器。按Ctrl Shift Esc打开切到性能标签点左侧的 CPU右下角有一行虚拟化。显示已启用固件层没问题问题在 Windows 内部。显示已禁用这就是根因BIOS/UEFI 里没开虚拟化后面所有操作都是白费力气直接跳到第 4 章。第二组看处理器和固件的详细状态。开一个 PowerShell跑Get-CimInstance Win32_Processor | Select-Object Name, VMMonitorModeExtensions, VirtualizationFirmwareEnabled, SecondLevelAddressTranslationExtensions三个属性的含义分别是VMMonitorModeExtensions是 CPU 硬件本身支不支持虚拟化扩展Intel 叫 VT-xAMD 叫 AMD-V现代 CPU 基本都是 TrueVirtualizationFirmwareEnabled是固件层有没有把它打开这个必须是 TrueSecondLevelAddressTranslationExtensions是二级地址转换Intel EPT / AMD RVIWSL2 硬性要求老一点的 CPU 可能是 False。如果VMMonitorModeExtensions是 True 而VirtualizationFirmwareEnabled是 False结论非常明确进 BIOS 开开关别在 Windows 里浪费时间。第三组看 hypervisor 到底在不在。同一条命令Get-CimInstance Win32_ComputerSystem | Select-Object HypervisorPresentHypervisorPresent为 True说明已经有一个 hypervisor 在跑了。注意这个值只告诉你有一个不告诉你是哪一个——这是后面排查第三方虚拟机软件冲突的关键线索。2.2 逐个确认 Windows 功能开关的真实状态很多人以为自己启用了功能其实只是点了勾没重启或者点错了功能项。用 DISM 看最准dism.exe /online /get-featureinfo /featurename:VirtualMachinePlatform dism.exe /online /get-featureinfo /featurename:Microsoft-Windows-Subsystem-Linux dism.exe /online /get-featureinfo /featurename:Microsoft-Hyper-V-All关注输出里的状态 : 已启用/State : Enabled那一行。三条命令对应的含义不一样别搞混VirtualMachinePlatform虚拟机平台这是 WSL2 唯一硬性依赖的功能位没有它必挂。Microsoft-Windows-Subsystem-Linux适用于 Linux 的 Windows 子系统负责提供wsl.exe入口和 WSL1 支持WSL2 下也是必装。Microsoft-Hyper-V-AllHyper-V 完整平台WSL2 其实不需要它。它提供的是完整的虚拟机管理能力Hyper-V 管理器、vmms 服务等体积大、影响面广。如果你在 Windows 家庭版上执行第三条会返回功能名称未知或者错误码0x800f080c。这不是故障家庭版本来就没有 Hyper-V 完整角色而家庭版跑 WSL2 是完全支持的只要VirtualMachinePlatform在就行。我见过有人因为这条报错误以为家庭版不支持 WSL2转头去重装系统实在没必要。2.3 事件日志里的证据链配置层面看不出问题时去事件查看器翻日志。位置在应用程序和服务日志 → Microsoft → Windows下面重点看三个Hyper-V-Hypervisor、Hyper-V-Worker、Hyper-V-Compute。注意这几个日志只有功能位启用后才会出现如果压根看不到说明功能位没装好。这里有个技巧Hyper-V-Hypervisor日志里如果有关于 hypervisor 启动失败、或者hypervisor 未启动的记录基本就锁定了问题在启动阶段而不是安装阶段。另外在Windows 日志 → 系统里搜来源为vmcompute、Hyper-V的条目也能看到 HCS 服务启动时的抱怨。坦白说事件日志在这个问题上给的直接帮助有限报错本身已经足够明确了。但当你怀疑是驱动冲突或安全软件拦截时日志是唯一能拿到证据的地方值得花两分钟扫一眼。3. 补齐 Windows 功能位DISM 与 PowerShell 两条路的取舍3.1 先分清楚你该补哪一个很多人一上来就把 Hyper-V 全家桶装上理由是报错里写着 HYPERV 嘛。这个思路在 Windows 10 早期确实管用因为那时候 WSL2 的依赖关系描述不清晰社区里口口相传就是装 Hyper-V。但现在的正确做法是只装必需的不装多余的。理由很实际。Hyper-V 完整角色一旦启用会改变整个系统的虚拟化行为vmms服务开始常驻第三方虚拟机软件VMware、VirtualBox的行为会随之变化某些对虚拟化敏感的游戏和反作弊组件也可能出问题。而你跑 WSL2 需要的只是 hypervisor 本身加一个虚拟机平台不需要那一整套管理界面。所以补功能位的顺序建议是先确认VirtualMachinePlatform和Microsoft-Windows-Subsystem-Linux都是启用状态重启后仍然报错再考虑要不要上完整的 Hyper-V。3.2 两条命令路径选一条走就行DISM 路径在管理员权限的 PowerShell 或 CMD 里跑dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestartPowerShell 路径Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All -NoRestart Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All -NoRestart两条路效果完全一样DISM 在旧版系统上兼容性稍好PowerShell 会自动处理依赖关系。我一般用 PowerShell因为可以直接配合Get-WindowsOptionalFeature做状态校验一条命令读、一条命令写闭环比较干净。如果你确实判断需要完整 Hyper-V比如同时要用 Windows 沙盒或者要在本机跑 Hyper-V 虚拟机再加一条dism.exe /online /enable-feature /featurename:Microsoft-Hyper-V-All /all /norestart3.3 重启不是可选项以及启用后立刻 wsl的翻车启用这类功能位后系统会提示需要重启。我必须强调这个重启是真·必须的不能跳过。原因是这些功能位涉及内核驱动和启动阶段的组件加载。DISM 只是在磁盘上把组件标记为启用真正把它们挂进内核启动链是下次开机时的事。如果启用后不重启直接跑wsl大概率看到的就是我们今天讨论的这个报错——因为它检查的还是旧的启动状态。我踩过一次更隐蔽的坑启用完功能位后用关机再开机和重启结果不一样。Windows 的快速启动Fast Startup默认开启时普通关机其实是混合休眠内核组件不一定完全重新加载。所以这一步我现在的习惯是明确点重启或者关机时按住 Shift 点关机。如果反复启用功能位都没效果先试试关掉控制面板里的启用快速启动或者干脆执行一次完整的shutdown /r /t 0。4. 让 hypervisor 真正跑起来bcdedit、内核隔离与安全启动的连带影响4.1 bcdedit 里那一行决定生死的 hypervisorlaunchtype如果功能位确认都启用了、也老老实实重启过还是同样的报错那基本可以锁定到这一条hypervisor 没有被启动加载。Windows 的启动配置里有一项专门控制 hypervisor 是否随系统启动用 bcdedit 查bcdedit /enum {current}在输出的末尾找hypervisorlaunchtype这一项。它的值只有两种有意义Auto随系统启动 hypervisorWSL2 需要这个。Off不启动 hypervisor。如果是Off或者这一项压根不存在那就改成Autobcdedit /set hypervisorlaunchtype auto然后重启。这一条命令解决了我遇到过的大半案例。那为什么会变成Off最常见的元凶是老版本 VMware Workstation。VMware 15.5.5 之前的版本和 Hyper-V 水火不容当时的官方建议就是关掉 Hyper-V很多人照着教程执行过bcdedit /set hypervisorlaunchtype off问题当时解决了但这条设置是持久的、写进启动配置的。后来你装了 WSL2或者升级了 Windows这条遗留设置就成了定时炸弹。装了又卸载的虚拟机软件、某些早期的模拟器和反作弊组件也有过类似的副作用。4.2 内核隔离与 VBS这个报错的反向线索这一节说一个反直觉的观察非常有用。Windows 的内核隔离 → 内存完整性也叫基于虚拟化的安全VBS功能本身就是依赖 hypervisor 运行的。所以它可以当作一个状态指示灯来用打开 Windows 安全中心 → 设备安全性 → 内核隔离看内存完整性是开是关。如果这里显示已关闭并且你记得自己没关过它再结合 WSL2 报HCS_E_HYPERV_NOT_INSTALLED基本可以确认 hypervisor 整体没在跑而不是 WSL 单独出问题。另一个途径是msinfo32在系统摘要里找基于虚拟化的安全性这一项正常运行时状态应该是正在运行。如果显示未启用含义和上面一致。反过来说如果你看到内存完整性正常运行、HypervisorPresent也是 True但 WSL2 仍然报这个错那问题就更偏向功能位缺失而不是hypervisor 没启动。这个交叉验证能帮你少走一半弯路。需要提醒的是内存完整性本身偶尔也会和某些老驱动冲突导致 hypervisor 加载失败。如果你的机器是最近才出问题、之前一直正常而且最近装过什么带内核驱动的软件杀软、外设驱动、虚拟声卡之类可以试着临时关闭内存完整性并重启看看 WSL2 是否恢复。这是排查手段不是长期方案——确认是它引起的就应该去找那个冲突的驱动而不是把安全功能长期关着。4.3 安全启动和固件开关的边界情况前面说过虚拟化开关要在 BIOS/UEFI 里打开。Intel 平台上这个选项通常叫Intel Virtualization Technology、VT-x、VanderpoolAMD 平台上叫SVM Mode、AMD-V。位置一般在 Advanced 或者 CPU Configuration 里不同品牌的 BIOS 差别很大找不到就搜一下自己主板型号加关键词。有几个边界情况值得单独说部分品牌机尤其是商用本的 BIOS 里虚拟化选项是被 OEM 锁住或者隐藏的需要先关掉安全启动或者进高级模式才能看到。改安全启动前建议先确认 BitLocker 状态避免触发恢复密钥流程。联想、戴尔、惠普的消费级机型通常不需要动安全启动虚拟化选项直接可见。开了虚拟化后如果还是显示已禁用检查一下是不是同时在 BIOS 里开了某些硬件虚拟化保护或可信执行相关的独占选项个别机型上这两者会互斥。固件层的排查一次性做完就好改完保存退出回到 Windows 里用任务管理器确认那一行变成已启用再进行后面的步骤。5. 在虚拟机里套娃跑 WSL2嵌套虚拟化的坑比你想的深5.1 VMware 宿主下的正确姿势如果你的 Windows 本身就是跑在 VMware Workstation 里的虚拟机那 WSL2 用不了的原因很明确虚拟机的 CPU 默认不透传虚拟化扩展给 guestguest 里的 hypervisor 没有硬件可依赖。判断方法很简单在 guest也就是你的 Windows里跑Get-CimInstance Win32_ComputerSystem | Select-Object Manufacturer, Model如果输出的型号里出现 VMware、VirtualBox、KVM、QEMU 之类的字样你就是套娃环境。VMware 这边的处理分两步。第一步是确保 VMware 版本足够新新版本对嵌套虚拟化的支持好得多。第二步在虚拟机的处理器设置里勾上虚拟化 Intel VT-x/EPT 或 AMD-V/RVI或者直接改.vmx配置文件加上这一行vhv.enable TRUE改完必须完全关闭虚拟机再开机挂起恢复不生效。开机后重复第 2 章的检查VirtualizationFirmwareEnabled和HypervisorPresent应该都变成 True这时候再装 WSL2 就顺了。还有一个前提是宿主自己也得开着虚拟化并且宿主上如果有别的东西占着虚拟化栈也可能让透传失效。5.2 Hyper-V 宿主的配置差异如果你的宿主是 Windows 用 Hyper-V在 guest 的 Windows 里跑 WSL2需要在宿主上给这台虚拟机开虚拟化扩展暴露。在宿主的 PowerShell管理员里执行Set-VMProcessor -VMName 你的虚拟机名 -ExposeVirtualizationExtensions $true同时有两个配套动作经常被漏掉一是关掉这台虚拟机的动态内存嵌套场景下动态内存容易导致 guest 启动异常二是如果 guest 需要联网要开启这台虚拟机网卡的 MAC 地址欺骗。这两条不做可能出现WSL2 起来了但网络不通的情况排查起来比启动失败更烦。不同宿主产品VMware、Hyper-V的语法不通用别看到一条命令就照抄先确认自己的宿主是哪一个。5.3 云主机和受限环境有时候真不是你的问题还有一类情况需要提前认清某些云主机机型在底层就不支持嵌套虚拟化或者需要在控制台里额外申请/切换机型才能开启。这种情况下你在 guest 里怎么改配置、怎么改 BIOS 都是无效的因为硬件能力压根没下发给你。判断方式还是那一条看HypervisorPresent和VirtualizationFirmwareEnabled。如果不管怎么改都是 False而你又确认自己确实在云主机里那就别折腾了去查该机型的规格说明或者直接换成支持嵌套虚拟化的规格。另外公司统一管理的设备上WSL 相关功能可能被组策略限制。这种情况下的现象通常是功能位启用后又被自动回退或者启用时报权限错误。如果你发现配置改了会自己变回来不用怀疑自己操作错了先确认一下是不是策略层面的限制。6. 修完之后怎么确认真的好了以及我反复踩过的几个坑6.1 一套完整的验证清单问题解决后别急着关窗口按这个顺序走一遍确保是彻底好了而不是暂时好了。wsl --shutdown wsl --status wsl --list --verbose第一条把可能残留的虚拟机实例彻底关掉避免旧状态干扰判断。第二条看默认版本是不是 2如果显示 1说明还没切换到 WSL2 架构用wsl --set-default-version 2改过来。第三条看每个发行版后面的版本号确认是 2。如果是从 WSL1 升级过来的还要单独对发行版做一次转换wsl --set-version Ubuntu-22.04 2这一步才是真正触发 Utility VM 创建的动作也正是最容易报HCS_E_HYPERV_NOT_INSTALLED的地方。转换过程要下载并解包整个根文件系统耗时取决于发行版大小别中途 CtrlC。最后进到发行版里做一次端到端验证uname -a ls /mnt/cuname -a的输出里应该带microsoft-standard-WSL2字样这是确认跑在 WSL2 内核上的最直接证据。ls /mnt/c能正常列出 C 盘内容说明跨系统文件访问正常。6.2 我反复踩过的几个坑第一个坑改完bcdedit忘了重启然后断定命令没用。这个我犯过不止一次。启动配置的改动百分百需要重启才生效没有任何例外。第二个坑在启用了 Hyper-V 的机器上装老版 VMware然后把hypervisorlaunchtype关掉。关掉之后 VMware 是好了但 WSL2 和 Windows 沙盒全线阵亡而且这个副作用要等到你下次用它们的时候才会发现。现在的正确做法是用支持 Windows 虚拟机监控程序平台Windows Hypervisor Platform的新版虚拟机软件让两边共存。如果发现自己的 hypervisorlaunchtype 是 Off 但完全不记得改过去翻翻之前装过的虚拟机软件教程。第三个坑把安装了当成运行了。功能位在控制面板里打着勾不代表 hypervisor 在跑。判断标准只有一个——任务管理器里虚拟化是不是已启用以及HypervisorPresent是不是 True。第四个坑忽略快速启动。前面提过混合关机状态下内核组件不一定重新加载导致我明明重启了其实没重启到位。反复无效时用shutdown /r /t 0来一次彻底重启。第五个坑发行版本身的状态也会干扰。有一次我确认 hypervisor 一切正常但某个特定发行版死活起不来最后是那个发行版的实例处于损坏状态。用wsl --unregister 发行版名注销后重新安装就好了。注意这条命令会删掉那个发行版里的所有数据执行前先把重要文件拷出来。6.3 环境通了之后顺手把终端体验调一下折腾完上面这些环境终于能用剩下的时间值得花在终端观感上——毕竟以后每天都要盯着它。VS Code 里用 WSL 写代码字体选择有两个方向。一是纯等宽编程字体JetBrains Mono、Cascadia Code、Fira Code 都是成熟选择连字效果用terminal.integrated.fontLigatures控制。二是带中日文对齐的等宽字体比如更纱黑体Sarasa Gothic系列它把中文、日文和拉丁字符统一到相同的字宽终端里对齐表格和日志输出会舒服很多。如果你想要接近 macOS 那种笔画均匀、渲染干净的观感优先选带中日文字形覆盖、且字重齐全的字体再用 Windows Terminal 的profiles.defaults.font统一配置比在每个 shell 里单独设置要省事。VS Code 侧的配置项是{ terminal.integrated.fontFamily: Sarasa Mono SC, JetBrains Mono, Consolas, terminal.integrated.fontSize: 14, terminal.integrated.fontLigatures: true }字体列表按优先级从左到右回退这样在没装主字体的机器上也不会变回宋体。多个字体名用引号包住逗号分隔。还有一个容易被忽略的点WSL 里的 locale。如果终端里中文显示成方块或者乱码检查/etc/default/locale或者.bashrc里的LANG设置配上对应语言包就行。这跟字体是两回事但表现得很像别搞混。最后说一句我的真实体会这类报错指向 A、实际原因在 B的问题最省时间的做法永远是先读状态、再动手。Get-CimInstance Win32_Processor、HypervisorPresent、bcdedit /enum {current}这三组信息花两分钟拿到手胜过盲目重装三次系统。
返回列表