
简介本资源是一套基于Electron框架将HTML网页打包为Windows可执行程序.exe的完整实践方案面向前端开发者、桌面应用入门学习者及需快速交付轻量级本地化Web应用的技术人员。内容聚焦全屏运行、任务栏隐藏、Esc键退出、自定义图标与文件名等关键落地细节覆盖从项目初始化、主/渲染进程通信到electron-packager打包全流程具备强实操性与工程参考价值。压缩包共2000个文件主体为5676个JS与1779个TS源码文件含Electron主进程逻辑、IPC通信模块及页面交互脚本辅以653个JSON配置、693个MD文档说明及15个已编译exe示例整体体积95.61MB结构清晰、即取即用。目前已有1158人学习下载资源附带完整目录组织、典型错误处理片段及跨平台构建注意事项可直接复用于教学演示、内部工具开发或客户定制化交付场景。1. Electron打包HTML为全屏EXE不是简单“双击运行”而是要彻底接管窗口行为、隐藏系统痕迹、控制退出逻辑你手头有个纯HTML页面——可能是内部培训系统、设备控制面板、自助终端界面或者一个离线数据看板。它在Chrome里跑得好好的但客户一句“我要个双击就开、关机都不留痕迹的.exe”你就得面对一连串现实问题任务栏图标一闪而过、AltTab还能切进去、Esc没反应、右上角关闭按钮暴露了底层Chromium、甚至exe图标还是Electron默认的蓝色方块……这不是“打包”而是“伪装”把网页包装成原生应用让它像Windows原生程序一样呼吸、响应、退场。本方案不依赖任何第三方GUI打包器如electron-builder的图形向导全程用命令行配置文件驱动重点解决四个硬性交付点全屏且覆盖任务栏、Esc键强制退出、任务栏图标彻底隐藏、EXE文件名与图标可定制。适合需要交付给非技术人员、部署在固定硬件如工控机、Kiosk终端或对UI一致性有强要求的场景。新手能照着敲完就出包老手能立刻定位到BrowserWindow的skipTaskbar、fullscreenable、kiosk等关键开关的组合逻辑。2. 从零初始化Electron项目精简结构 必备依赖 HTML入口绑定Electron打包不是“把HTML拖进某个工具”而是构建一个可控的Node.js运行时环境让Chromium加载你的HTML。我们跳过electron-forge这类封装层用最轻量的方式启动——因为越透明越容易改窗口行为。2.1 初始化最小化项目结构新建空文件夹执行npm init -y npm install --save-dev electronlatest提示不要全局安装Electron。--save-dev确保版本锁定在package.json中避免CI/CD环境因全局版本不一致导致打包失败。当前稳定版为v30.x2024年主流LTS若需兼容旧Win7系统可降级至v25.x但需同步检查Node.js最低支持版本。项目结构只需4个文件my-kiosk-app/ ├── package.json ├── main.js # Electron主进程入口 ├── index.html # 你的原始HTML可直接放这里或指向子目录 └── assets/ └── icon.ico # 后续替换用的图标文件必须是ICO格式含256x256尺寸2.2 编写主进程脚本main.js窗口行为的总开关这是全篇最关键的代码。它不负责业务逻辑只做三件事创建窗口、加载HTML、拦截系统事件。所有“全屏”“隐藏任务栏”“Esc退出”的控制点都在这里const { app, BrowserWindow, globalShortcut, screen } require(electron); const path require(path); function createWindow() { // 获取主屏幕尺寸适配多屏 const { width, height } screen.getPrimaryDisplay().workAreaSize; const win new BrowserWindow({ width: width, height: height, x: 0, y: 0, // 【核心参数1】全屏且不可缩放、无边框 fullscreen: true, frame: false, transparent: false, // 【核心参数2】任务栏行为完全隐藏AltTab不可见 skipTaskbar: true, // 【核心参数3】禁用窗口管理功能防止用户拖拽/调整大小 resizable: false, movable: false, minimizable: false, maximizable: false, // 【核心参数4】Kiosk模式禁用F11、CtrlShiftI等调试快捷键 kiosk: true, // 【核心参数5】图标设置仅Windows生效路径必须为绝对路径 icon: path.join(__dirname, assets, icon.ico), // 禁用web安全限制仅限可信本地HTML生产环境慎用 webPreferences: { nodeIntegration: true, contextIsolation: false, enableRemoteModule: false, // 禁用缩放以保证全屏像素精准 zoomFactor: 1.0, // 禁用默认右键菜单避免暴露Chromium disableHtmlFullscreenWindowResize: true } }); // 【关键操作】加载本地HTML绝对路径避免协议错误 win.loadFile(path.join(__dirname, index.html)); // 【关键操作】注册全局快捷键Esc退出应用即使焦点不在窗口内也生效 globalShortcut.register(Escape, () { app.quit(); }); // 【关键操作】窗口关闭时清理快捷键防内存泄漏 win.on(closed, () { globalShortcut.unregister(Escape); }); // 【可选】开发时打开DevTools生产包请注释掉 // win.webContents.openDevTools(); return win; } // Electron生命周期控制 app.whenReady().then(() { createWindow(); // 【重要】阻止默认关闭行为否则点击X按钮会直接退出无法拦截 app.on(window-all-closed, () { if (process.platform ! darwin) app.quit(); }); app.on(activate, () { if (BrowserWindow.getAllWindows().length 0) createWindow(); }); }); // 【重要】处理Windows平台下“关闭所有窗口”时的退出逻辑 app.on(before-quit-forced, () { globalShortcut.unregister(Escape); });逻辑说明kiosk: true是比fullscreen: true更严格的模式它不仅全屏还禁用所有系统级快捷键F11切换全屏、CtrlShiftI打开开发者工具这是Kiosk终端的刚需skipTaskbar: true让窗口彻底从任务栏消失但注意它不等于隐藏任务栏本身那是系统级设置只是让这个窗口不显示图标globalShortcut.register(Escape)是唯一能捕获全局Esc事件的方式win.on(keydown)在窗口失焦时无效loadFile()而非loadURL(file://...)避免跨域策略报错尤其当HTML内含script srcjs/app.js等相对路径资源时更稳定。2.3 配置package.json定义入口与构建目标package.json不仅是依赖清单更是Electron的“启动说明书”。关键字段必须精确{ name: kiosk-terminal, version: 1.0.0, description: Full-screen kiosk application for industrial terminal, main: main.js, scripts: { start: electron ., build: electron-packager . kiosk-terminal --platformwin32 --archx64 --electron-version30.3.0 --iconassets/icon.ico --overwrite --outdist }, devDependencies: { electron: ^30.3.0 } }参数说明main: main.js明确指定主进程入口不可省略build脚本使用electron-packager非electron-builder因其配置粒度更细、无隐藏行为--platformwin32生成Windows EXE--archx6464位架构若需32位改为ia32--electron-version30.3.0必须与devDependencies中版本严格一致否则打包时会重新下载耗时且易失败--iconassets/icon.ico图标路径为相对路径electron-packager会自动嵌入到EXE资源中--overwrite每次构建前清空dist目录避免旧文件残留--outdist输出目录生成的EXE将位于dist/kiosk-terminal-win32-x64/kiosk-terminal.exe。3. 图标与文件名定制ICO格式规范 Windows资源编辑技巧Electron打包时指定--icon参数仅影响EXE文件的图标显示但不会修改文件名。文件名由electron-packager命令中的第二个参数即kiosk-terminal决定。很多人卡在这一步图标换了但EXE名字还是kiosk-terminal.exe客户要求叫FactoryControl.exe。3.1 ICO图标制作尺寸、颜色深度与工具链Windows EXE图标不是简单PNG转ICO。它必须包含多个尺寸16×16, 32×32, 48×48, 256×256和不同色深8-bit, 24-bit, 32-bit带Alpha否则高分屏下显示模糊或缺失。常见翻车点用在线转换网站生成的ICO只有16×16一种尺寸 → 高分屏显示为马赛克PNG源图背景为白色 → 256×256尺寸在深色任务栏上显示白边未嵌入Alpha通道 → 图标边缘锯齿。正确做法推荐免费工具用Figma或PhotoShop设计一张512×512像素、透明背景、RGB色彩模式的PNG访问 https://icoconvert.com 无需注册上传PNG勾选所有尺寸尤其256×256选择“32-bit with Alpha”下载ICO文件保存为assets/icon.ico。验证方法右键EXE文件 → “属性” → “详细信息”选项卡 → 查看“图标”是否清晰或用 Resource Hacker 打开EXE展开Icon Group节点确认存在256×256 32bpp条目。3.2 修改EXE文件名重命名 资源字符串同步electron-packager生成的EXE名为kiosk-terminal.exe命令中第二个参数。要改成FactoryControl.exe只需改命令electron-packager . FactoryControl --platformwin32 --archx64 --electron-version30.3.0 --iconassets/icon.ico --overwrite --outdist但这还不够。Windows资源管理器显示的“文件描述”“产品名称”等元数据仍为默认值右键属性里看到的还是kiosk-terminal。需用Resource Hacker注入自定义字符串用Resource Hacker打开dist/FactoryControl-win32-x64/FactoryControl.exe展开左侧树形菜单Version Info→1→StringFileInfo→040904B0英文语言双击右侧列表中的FileDescription将值改为Factory Control Terminal同样修改ProductName、InternalName、OriginalFilename此项必须与EXE文件名一致即FactoryControl.exe点击“编译脚本” → “文件” → “保存”。注意OriginalFilename必须与实际EXE名完全一致包括大小写和扩展名否则某些杀毒软件会报“文件名与签名不匹配”。3.3 防止图标缓存Explorer重启与注册表清理即使替换了ICOWindows可能因图标缓存仍显示旧图标。强制刷新方法快速法按WinR输入ie4uinit.exe -ClearIconCache回车彻底法打开任务管理器 → 结束explorer.exe进程按WinR输入%localappdata%\IconCache.db删除该文件任务管理器 → “文件” → “运行新任务” → 输入explorer.exe。4. 全屏与任务栏隐藏的避坑指南4个真实翻车现场与血泪解法Electron的窗口API看似简单但fullscreen、kiosk、skipTaskbar三者组合极易产生冲突。以下是某工业终端项目实测踩过的坑每一条都附带复现条件和验证方式。4.1 现象全屏后任务栏仍部分可见尤其Win10/11底部1px原因fullscreen: true仅让窗口占据屏幕可用区域workAreaSize而Windows任务栏默认有“自动隐藏”功能当设置为“始终显示”时workAreaSize会减去任务栏高度但窗口Y坐标从0开始导致底部被任务栏遮挡。验证在main.js中打印screen.getPrimaryDisplay().workAreaSize对比screen.getPrimaryDisplay().size差值即为任务栏高度。解决不用workAreaSize强制用size并设置y: 0const { width, height } screen.getPrimaryDisplay().size; // 改用size而非workAreaSize // 后续创建窗口时保持x:0, y:0补充若客户要求“任务栏自动隐藏”需在部署前用PowerShell脚本预设系统策略此非Electron控制范围。4.2 现象skipTaskbar: true失效任务栏图标闪烁后出现原因skipTaskbar必须在窗口创建时设置且不能在win.show()之后再调用win.setSkipTaskbar(true)。更隐蔽的触发条件是main.js中createWindow()被调用两次如app.on(activate)未加判断。验证在createWindow()开头加console.log(Creating window...)启动时观察是否重复打印。解决确保createWindow()全局只执行一次并在app.on(activate)中加守卫app.on(activate, () { if (BrowserWindow.getAllWindows().length 0) { createWindow(); // 仅当无窗口时才创建 } });4.3 现象Esc键无反应或仅在窗口聚焦时有效原因globalShortcut.register()必须在app.whenReady()之后、createWindow()之前调用否则注册失败且app.quit()会触发before-quit-forced事件若此处未注销快捷键下次启动时会报“快捷键已注册”错误。验证在globalShortcut.register回调中加console.log(Esc pressed)启动后按Esc看控制台是否输出。解决严格按生命周期顺序注册并在退出前注销app.whenReady().then(() { // ✅ 先注册全局快捷键 globalShortcut.register(Escape, () { console.log(Esc pressed, quitting...); app.quit(); }); createWindow(); }); // ✅ 在before-quit-forced中注销 app.on(before-quit-forced, () { globalShortcut.unregister(Escape); });4.4 现象打包后EXE双击无反应或黑窗口闪退原因index.html路径错误loadFile()传入相对路径、icon.ico文件不存在、或electron-packager版本与Electron不匹配。验证进入dist/xxx-win32-x64/目录按住Shift右键 → “在此处打开Powershell窗口”执行.\xxx.exe观察终端是否报错若报Cannot find module electron说明node_modules未被打包需确认electron-packager命令中未加--no-prune若报Failed to load module检查index.html中script标签路径是否为相对路径如./js/app.js应确保该文件与HTML同目录。解决所有资源路径用./开头避免../跨目录构建前执行npm prune --production清理开发依赖减少包体积用--prune参数默认开启确保只打包dependencies。5. 生产环境加固静默启动、进程守护、防误关机交付给客户前EXE不能只是“能跑”还要“跑得稳、关得准、查得清”。以下三个技巧来自某自助终端项目的落地经验解决真实运维痛点。5.1 静默启动消除CMD黑窗口Windows专属Electron默认启动时会弹出Node.js命令行窗口CMD在Kiosk模式下极其突兀。解决方案是将EXE的子进程类型设为windows而非console用 Resource Hacker 打开dist/xxx-win32-x64/xxx.exe左侧展开Version Info→1→VarFileInfo右侧找到Translation双击将0409 04B0改为0409 04E4即把04B0→04E4保存后CMD窗口消失。原理04B0对应SUBLANG_ENGLISH_US04E4对应SUBLANG_ENGLISH_CAN但实际效果是切换进程子系统为windowsGUI而非console。这是Windows PE头的hack无副作用。5.2 进程守护崩溃后自动重启防HTML JS异常退出Kiosk终端不允许人工干预。若index.html中JS报错导致win.webContents崩溃窗口会直接关闭。添加自动重启逻辑// 在main.js中createWindow()后添加 win.webContents.on(crashed, () { console.log(Renderer process crashed, restarting...); // 延迟重启避免连续崩溃 setTimeout(() { if (win.isDestroyed()) return; win.reload(); }, 2000); }); // 监听渲染进程未捕获异常 win.webContents.on(unresponsive, () { console.log(Renderer unresponsive, force reload); win.webContents.send(force-reload); });并在index.html的JS中监听// index.html内 window.addEventListener(DOMContentLoaded, () { ipcRenderer.on(force-reload, () { location.reload(); }); });5.3 防误关机物理按键拦截仅限工控机某些工控机面板有物理“电源键”按下会直接切断主机电源。需在OS层拦截。此非Electron能力范围但可提供部署脚本创建disable-power-button.ps1PowerShell脚本# 禁用电源按钮需管理员权限 powercfg /setacvalueindex scheme_current sub_buttons pbaction 0 powercfg /setdcvalueindex scheme_current sub_buttons pbaction 0 powercfg /setactive scheme_current将其加入开机启动项通过任务计划程序确保每次启动生效。最后一句我坚持在每个交付包里放一个debug.log文件用fs.appendFile记录app.on(ready)、win.on(show)、globalShortcut.register成功与否。当客户说“点不开”我第一句就问“log里有没有‘Esc pressed’”——不是玄学是把黑匣子变成白盒。希望帮到你。本文还有配套的精品资源点击获取