eNSP 是华为的网络模拟器,做网络的朋友基本都用过。它底层靠 VirtualBox 跑每一台虚拟设备——启动一台路由器、交换机,实际上就是 VirtualBox 拉起一个虚拟机镜像。
但是,我要说但是了。
华为官方早就停更 eNSP 了,它死死绑定 VirtualBox 5.2。问题是现在的机器——Windows 11,尤其是开了 Hyper-V / WSL2 的开发机——根本装不上 VirtualBox 5.2。于是大多数教程的结论都是那一句老话:
“卸载干净,降级到 VirtualBox 5.2.44 就好了。”
2022 年这话管用。2026 年,这话基本失效了。
为什么“降级”这条路走不通了
新机器上想降级 VirtualBox 5.2,你会撞上两堵墙:
- 装不上。Win11(特别是 24H2)+ Hyper-V/WSL2 开着的环境,VirtualBox 5.2 的驱动签名、内核模式组件跟现代系统的虚拟化栈冲突,装到一半失败,或者装上了启动设备直接 报错 40。
- 关不掉 Hyper-V。很多人吃饭的家伙就是 WSL2、Docker Desktop、Windows 沙箱——这些全依赖 Hyper-V。为了跑个 eNSP 把 Hyper-V 关了,等于把开发环境废了。
所以真正的死结是:要么 eNSP,要么 WSL2,二选一。这显然不能接受。
换个思路:不动 VirtualBox,骗过 eNSP
既然 5.2 装不上、Hyper-V 关不得,那能不能装现版本的 VirtualBox 7.x,让 eNSP 以为自己面对的还是 5.2?
eNSP 通过 COM 接口调用 VirtualBox。它认死 5.2,卡点有两道:
- 版本检查:eNSP 启动时读注册表里的 VirtualBox 版本号,不是
5.2.x直接拒绝,弹VirtualBox version is not supported。 - 接口不兼容:就算骗过版本号,eNSP 调用
IVirtualBoxCOM 接口时,5.2 和 7.2 的虚函数表(vtable)布局根本对不上,调用会落到错误的方法上,进程直接崩。
第一道好办,把版本号伪装成 5.2.44 即可。难的是第二道。
vtable 为什么对不上
COM 接口本质是一张函数指针表,调用方按固定槽位索引取方法。eNSP 按 5.2 的槽位去调,真实对象却是 7.2 的布局,对不上的原因有三层:
- 基类变了,整体平移 +4。5.2 的
IVirtualBox派生自IUnknown(3 个基础槽),7.2 派生自IDispatch(7 个基础槽),后面所有方法整体后移 4 格。 - 中间插入了新属性。7.2 在表中间新增了若干属性,不是追加在末尾,从插入点往后偏移不再恒定。
- 方法重排 + 新增。比如
createDHCPServer在 5.2 是第 3 个方法,到 7.2 排到了第 22 个。每个槽位都得单独查表映射,毫无规律。
我把两个版本的接口逐一对照,复原出一张完整的 53 槽映射表。这张表是整个方案的地基。
解法:一层 COM 垫片
基于这张映射表,做一个夹在 eNSP 和真实引擎之间的 COM 适配层:
- 对 eNSP 呈现一张 5.2 形状的接口表面;
- 收到调用后,按映射表转发给真实的 7.2 引擎;
- 跨版本转发用按方法名的后期绑定,规避硬编码偏移在不同小版本间漂移的问题;
- 调用约定上做
__thiscall到__stdcall的栈平衡转换——这点最关键,早期版本就是因为返回字节数不匹配、栈指针错位,进程直接c0000005崩溃。
加上版本号伪装、补齐 x86 运行时(很多机器报错 40 的根因其实是缺 32 位 VC++ 运行时)这几座配套小桥,整条链路就通了。
成果
最终效果:装现版本的 VirtualBox 7.x,原版 eNSP 直接跑起来,路由器、交换机、防火墙都能正常启动进 CLI。全程不降级 VirtualBox、不关 Hyper-V/WSL2,WSL2 和 Docker 照常用。开了 Hyper-V 的机器走 WHP 后端,性能略有损耗但功能正常。
这套垫片我开源了,免费,地址放在文末。如果你也卡在“eNSP 还是 WSL2”这个二选一里,希望能帮上忙。
开源地址
GitHub 搜 ensp-vbox-shim 即可(仓库 LBXaaa/ensp-vbox-shim),免费开源。