Winboat install.bat 拆解OEM 首启如何拉起双 Windows 服务【免费下载链接】winboatRun Windows apps on Linux with ✨ seamless integration项目地址: https://gitcode.com/GitHub_Trending/wi/winboat在 WinBoat 的 Configure Windows 向导里点下 Next 之后真正决定这台 Windows 虚拟机能不能被远程驱动的是藏在 guest_server/install.bat 里的一段批处理。它借助 Windows 的 OEM 首启机制在完全无人值守的情况下把 Guest Server 与 Updater 两个 Go 服务注册成系统服务、放行防火墙端口再挂好开机时间同步任务——整条链路让 Linux 侧装完即用全程不需要人工登录 Windows 桌面。OEM 首启install.bat 到底什么时候被执行Windows 有个少有人用的特性系统第一次完成引导时会自动执行C:\OEM目录下的初始化脚本专为厂商预装设计。WinBoat 正是把这条一次性通道借来用——用户根本不用碰 Windows脚本在虚拟机冷启动的瞬间就跑完了。Linux 侧的准备工作在 src/renderer/lib/install.ts 的createOEMAssets里完成它把guest_server资源目录下的oem载荷server\、updater\、nssm.exe、install.bat、RDPApps.reg拷进WINBOAT_DIR/oem同时用crypto.randomUUID()生成一个鉴权 token写入本地guest_token并一并塞进 oem 目录。这个目录随后被容器挂载成 VM 的C:\OEM。所以 install.bat 运行时C:\OEM里已经躺好了全部物料包括那把后面防火墙鉴权要用的钥匙。为什么在拷文件之前先给 Defender 加排除项这是参考性文档里常被略过、却直接影响首启成败的一步。install.bat 建好安装目录后、xcopy之前插了一条 PowerShellif not exist %WB_DIR% mkdir %WB_DIR% powershell -ExecutionPolicy Bypass -Command Add-MpPreference -ExclusionPath %WB_DIR% xcopy %OEM_DIR%\* %WB_DIR%\ /Y /EAdd-MpPreference -ExclusionPath把C:\Program Files\WinBoat加进 Windows Defender 的排除列表。顺序是关键必须先排除、后写入否则大批 guest 二进制在落地时会被实时扫描逐个拦截首启阶段既慢又可能被误杀。排除后再xcopy /Y /E递归覆盖保证server、updater等目录的完整落盘。RDPApps.reg 一次性放开远程桌面白名单guest_server/RDPApps.reg 在 install.bat 第一行业务命令就被reg import导入。它的目的比配置远程桌面更具体——WinBoat 靠 RDP 远程驱动应用而 Windows 默认的 RemoteApp 白名单会限制哪些程序允许被远程会话运行于是这个 reg 文件直接把闸门全打开fDisabledAllowListdword:00000001 fAllowUnlistedRemoteProgramsdword:00000001 AutoAdminLogon0fDisabledAllowList与fAllowUnlistedRemotePrograms一组合意味着未列名程序也能在 RDP 会话里跑关掉AutoAdminLogon避免开机自动以管理员登录后面还跟着忽略远程键盘布局、禁用网络是否可被发现弹窗。之所以做成 reg 文件而非散装的reg add是因为这些值一次性导入即可、且要在任何服务启动前就位。nssm 一次注册两台服务参数各管一摊nssm 相当于一个服务包装器把普通 exe 注册成能被 SCM服务控制管理器管理、开机自启、崩溃可重启的系统服务。install.bat 用它一次拉起两台服务——这是很多只讲一个服务的解读漏掉的重点%NSSM% install WinBoatGuestServer %WB_DIR%\server\winboat_guest_server.exe %NSSM% set WinBoatGuestServer Start SERVICE_AUTO_START %NSSM% set WinBoatGuestServer AppDirectory %WB_DIR%\server %NSSM% set WinBoatGuestServer ObjectName NT AUTHORITY\SYSTEM第二个服务WinBoatGuestServerUpdater是同样一套只是指向updater\winboat_guest_server_updater.exe、AppDirectory设为updater。几个set参数各管一摊Start SERVICE_AUTO_START定启动类型AppDirectory锁定工作目录两个服务必须各指各的目录因为 server 会被替换ObjectName NT AUTHORITY\SYSTEM给足权限去碰注册表和防火墙。为什么非要拆成两台看 guest_server/cmd/updater/swap.go 就懂了Updater 的职责是热替换server——它用同卷rename把server\原子地换成server.new\失败再回滚。一个负责更新别人的进程不能把自己也卷进替换流程否则看门人自己也得被更新。于是 server 可热更updater 永远不动注释里直接标了never updated。端口 7148 与 7150 从哪来防火墙为何只开这两个服务跑起来后host 侧要能连上它们而 Windows 默认入站是拒的所以 install.bat 用netsh补两条规则netsh advfirewall firewall add rule nameAllow WinBoat API 7148 dirin actionallow protocolTCP localport7148 netsh advfirewall firewall add rule nameAllow WinBoat Updater 7150 dirin actionallow protocolTCP localport7150这两个端口不是拍脑袋定的而是和 src/renderer/lib/constants.ts 严格对齐GUEST_API_PORT 7148Guest Server API、GUEST_UPDATE_PORT 7150Updater。host 侧再通过COMPOSE_PORT_MAPPINGS把127.0.0.1的本地端口47271→7148、47274→7150转发进 VM。之所以只开这两个 TCP 口是因为 host 驱动 guest 只走 API 和更新这两条路QMP、noVNC、RDP 各走各自的映射不挤在这里。值得留意的是端口开了≠安全。guest 侧的 guestauth 中间件要求请求同时满足带对Bearer token就是首启时塞进C:\OEM的那把且Host头是 loopback。这层校验把 DNS rebinding 之类的攻击挡在门外——防火墙只负责放行鉴权负责认人。收尾一条 schtasks 强制开机同步时钟install.bat 的最后一行容易被当成锦上添花其实对 RDP 和更新都挺关键schtasks /create /tn TimeSyncTask /sc ONSTART /RL HIGHEST /tr \%WB_DIR%\server\scripts\time-sync.bat\ /RU SYSTEM它建了个开机任务TimeSyncTask每次 VM 启动都以 SYSTEM 跑 scripts/time-sync.bat内容就是net stop w32time、net start w32time、w32tm /resync——重启时间服务并强制与上游对时。VM 与 host 的时钟会漂移而 RDP 会话、证书、更新校验都依赖时间开机强制对齐一次能省掉一堆难查的诡异故障。install.bat 本质是一条首启即焚的一次性链路注释里 updater 标着never updatedguest_token一旦随 oem 落盘就不再变化guest 侧真正的热更新能力全押在server\那次 rename 替换上。所以哪天想给 guest 加第三个服务改的只能是 install.bat 本身而不是那个永远站桩的 Updater。【免费下载链接】winboatRun Windows apps on Linux with ✨ seamless integration项目地址: https://gitcode.com/GitHub_Trending/wi/winboat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考