实现打开页面跳转系统浏览器

期望实现客户端内有些页面跳转用户自己电脑的浏览器,而不是新开 electron 窗口

思路:拦截 window.open,识别参数处理
文档:https://www.electronjs.org/docs/api/web-contents#contentssetwindowopenhandlerhandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const mainWindow = new BrowserWindow({
width: 1000,
height: 600,
});

// some unrelated things

mainWindow.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('http')) {
shell.openExternal(url);
return { action: 'deny' };
}
return { action: 'allow' };
});

替换应用图标

两种方式,一是创建 BrowserWindow 实例时配置,二是调用实例的方法设置

相关文档:https://www.electronjs.org/docs/api/browser-window

1
2
3
4
5
6
7
8
// 方式一
const win = new BrowserWindow({
icon: 'assets/images/app.png'
});

// 方式二
win.setIcon('assets/images/app.png');


win.setIcon 问题

代码段如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const mainWindow = new BrowserWindow({
width: 1000,
height: 600,
minWidth: 1000,
minHeight: 388,
});
const appIcon = 'assets/images/app';
switch (process.platform) {
case 'darwin':
mainWindow.setIcon(path.join(__dirname, `${appIcon}.icns`));
break;
case 'win32':
mainWindow.setIcon(path.join(__dirname, `${appIcon}.ico`));
break;
default:
mainWindow.setIcon(path.join(__dirname, `${appIcon}.png`));
break;
}

遇到报错

1
2
3
4
5
6
A JavaScript error occurred in main process

Uncaught Exception:
Error: No native build was found for platform=win32 arch=x64 runtime=electron abi=89 uv=1 libc=glibv node=14.16.0 electron=13.0.0 webpack=true loaded from: C:\Users\liluhui\Desktop\lampbody-qnbot\.webpack
at Function.load.path
...
1
2
3
4
5
A JavaScript error occurred in main process

Uncaught Exception:
Error: Failed to load image from path 'C:\Users\liluhui\Desktop\lampboy-qnbot\.webpack\main\assets\images\app.ico' at App.createWindow
...

看起来是没有在 .webpack\ 下找到文件,看了下确实 assets 整个目录都不存在,继续翻看下架构里,主要是看 webpack 任务,的确是没有对这个目录进行拷贝输出,加一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// webpack.main.config.js
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: path.join(__dirname, 'src/assets'), to: "assets" }
]
})
]


//webpack.rules.js
{
test: /\.(jpg|png|svg|ico|icns)$/,
loader: "file-loader",
options: {
name: "[path][name].[ext]",
publicPath: "..",
context: "src",
},
}

跑起来确认下,目录和文件都有了
image.png


隐藏窗口菜单栏

期望隐藏/关掉窗口的菜单栏
image.png

1
2
// set hide MenuBar
mainWindow.setMenuBarVisibility(false);

注意不要用 autoHideMenuBar 字段,用户使用 Alt 快捷键依然会呼出菜单栏


网页与客户端通信实现

electron 主进程 main 与 网页 renderer 通信

方案:ipc通信,https://www.electronjs.org/docs/api/ipc-main#ipcmainhandlechannel-listener

1
2
3
4
5
6
7
8
9
10
11
// Main process
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
const result = await somePromise(...args)
return result
})

// Renderer process
async () => {
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
// ...
}


electron-forge make 打包exe图标配置

看了下打包我用的 Squirrel.Windows,对应 配置文档

1
2
3
4
5
6
7
8
9
"makers": [
{
"name": "@electron-forge/maker-squirrel",
"config": {
"setupIcon": "src/assets/images/app.ico", // 这个必须 ico ,就挺离谱..
"iconUrl": "src/assets/images/app"
}
}
],
  1. 注意文件地址不管有没有指定后缀,maker-squirrel 有些配置会判断 platform 自动补充后缀,所以准备好同名的 png、ico、icns



@electron-forge/maker-squirrel setupIcon 报错

1
2
3
No dice: Failed with exit code: 1
Output:
Fatal error: Unable to load file

确认了路径没有问题,然后查到了相关的问题但没能解决,调的过程猜测编码问题,试了下程序名改成英文名解决了…

相关问题



electron-squirrel-startup 创建快捷方式无效/失败

一开始是发现 ProductName 是中文就成功,是英文就失败… 当然底层原因肯定不是这个,中文应该是触发了 electron-forge 相关包的坑,英文下应该是执行成功了。溯源去找运行地址,发现报错是 Couldn’t run Squirrel hook, ............ 0x80004005 请求的操作需要提升。

image.png

真实原因是提升权限的应用在 Squirrel 的这个 hook 事件是无效的,对应是由于 win32metadata requested-execution-level

解决方法是重写下 electron-squirrel-startup 这个包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var path = require('path');
var spawn = require('child_process').spawn;
var app = require('electron').app;

var run = function(args, done) {
var updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');
// debug('Spawning `%s` with args `%s`', updateExe, args);
spawn(updateExe, args, {
detached: true
}).on('close', done);
};

var check = function() {
if (process.platform === 'win32') {
var cmd = process.argv[1];
// debug('processing squirrel command `%s`', cmd);
var target = path.basename(process.execPath);

// 增加 --squirrel-firstrun 这个handle
if (cmd === '--squirrel-firstrun') {
run(['--createShortcut=' + target + ''], app.quit);
return true;
}

if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
run(['--createShortcut=' + target + ''], app.quit);
return true;
}
if (cmd === '--squirrel-uninstall') {
run(['--removeShortcut=' + target + ''], app.quit);
return true;
}
if (cmd === '--squirrel-obsolete') {
app.quit();
return true;
}

}
return false;
};

module.exports = check();

关联问题: