之前做Electron开机自启动(Windows)的时候用到了auto-launch
包,当时程序安装路径是写死的,如果安装的时候手动选择路径,开机启动就会无效
今天按照计划填坑,修改从注册表获取程序安装路径,本篇文章记录两项内容——获取Electron程序信息的注册表位置,从注册表中获取Electron的安装路径
(一)获取Electron程序信息的注册表位置
程序使用electron-builder
打包,之前一直很困惑,因为程序安装后创建的注册表位置是类似这样的路径
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\50c1930e-15ef-5300-9367-f5b10795c0e4
问题随之出现,后边的50c1930e-15ef-5300-9367-f5b10795c0e4
是builder随机生成的,我如果在之后获取这个值呢,刚开始的思路是在installer.nsh
中看看能不能手动修改一下INSTALL_REGISTRY_KEY
发现不行,偶然间查看文档,发现可以手动设置guid
(文档不推荐手动设置,但是自己清楚想要做什么就完全没问题了)
"nsis": {
"shortcutName": "desktop-icon-name",
"guid": "50c1930e-15ef-5300-9367-f5b10795c0e4",
"oneClick": false,
"perMachine": true,
"allowToChangeInstallationDirectory": true
}
设置好guid后,electron-builder
在构建应用的时候就会使用这个指定值了
PS:这个UUID是v5版本的,如果你用Python,可以用下面命令来生成这个UUID
# -*- coding: utf-8 -*-
import uuid
print(uuid.uuid5(uuid.NAMESPACE_DNS, 'somestring'))
(二)从注册表中获取Electron的安装路径
知道了安装程序的注册表位置,修改注册表的东西就方便多了,比如换个控制面板里应用的版本号
Node.js获取/修改注册表值的库我找到两个——regedit
与windows-registry
使用regedit
代码如下:
获取安装路径:
regedit
.list(['HKLM\\SOFTWARE\\50c1930e-15ef-5300-9367-f5b10795c0e4'])
.on('data', function(entry) {
console.log(entry.data);
let program_location = entry.data.values.InstallLocation.value + '\\your-exe.exe';
console.log(program_location);
})
.on('finish', function() {
console.log('Get location from regedit finished~');
});
这样写后不久打包测试,发现打成asar包的时候运行会报错,不贴图片了,报错与这个Issues很像
但是问题已经被解决关闭了,不知道为什么我还会遇到这个问题
于是想着看看有没有别获取注册表值的方式
var Key = require('windows-registry').Key;
var windef = require('windows-registry').windef;
var key = new Key(windef.HKEY.HKEY_LOCAL_MACHINE, 'SOFTWARE\\50c1930e-15ef-5300-9367-f5b10795c0e4', windef.KEY_ACCESS.KEY_ALL_ACCESS);
var value = key.getValue('InstallLocation');
console.log(value);
换用了windows-registry
后,代码看起来清爽了不少,接着就出项了另一个问题,这个包用到了ffi... 于是在Electron下使用,妥妥的需要再编译一下
cd ./node_modules/ffi/ && node-gyp rebuild --target=2.0.0 --arch=ia32 --target_arch=ia32 --dist-url=https://atom.io/download/electron && cd ../ref && node-gyp rebuild --target=2.0.0 --arch=ia32 --target_arch=ia32 --dist-url=https://atom.io/download/electron
在项目根目录运行即可。可能遇到下载失败,请看(三),另外编译需要用到VS编译器,Python等
(三)编译需要用到的头文件等
编译过程中可能遇到网网络问题(ETIMEOUT 错误), 导致从https://atom.io/download/electron
下载包失败,我看了下我的缓存目录,正好有几个版本(1.8.2, 1.8.7, 2.0.0, 2.0.2)
下载:【iojs-1.8.2.zip】 【iojs-1.8.7.zip】 【iojs-2.0.0.zip】 【iojs-2.0.2.zip】
下载后解压缩放在目录:C:\Users\Administrator\.node-gyp\
比如:C:\Users\Administrator\.node-gyp\iojs-2.0.2
路径下能看到installVersion文件即可,然后编译就会使用缓存,另外,我发现一个目录C:\Users\Administrator\.electron-gyp
这个里面的内容与.node-gyp
是一样的(我看了对应版本lib的md5),我不确定是谁用到了它,可能是electron-builder在打包时自动编译使用?未验证
(四)Rust写的修改注册表值的程序
为了增加软件的物种多样性(其实是闲的),我之前用Rust的包做了修改注册表的程序,有时间还是修改回npm包,省得还得用child_process...
控制面板里Electron程序显示内容是在Uninstall项里(Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\50c1930e-15ef-5300-9367-f5b10795c0e4
)
extern crate winreg;
use std::path::Path;
use winreg::RegKey;
use winreg::enums::*;
fn main() {
let args: Vec<_> = std::env::args().collect();
if args.len() < 3 {
println!("Usage: {} <guid_string> <version>",
args[0]);
std::process::exit(1);
}
let guid_string = &args[1];
let version = &args[2];
println!("guid_string: {}", guid_string);
println!("version: {}", version);
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
let path = Path::new("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall").join(guid_string);
let key = hklm.create_subkey(&path).unwrap();
println!("====== Before ======");
let old_name: String = key.get_value("DisplayName").unwrap();
println!("DisplayName = {}", old_name);
let old_version: String = key.get_value("DisplayVersion").unwrap();
println!("DisplayVersion = {}", old_version);
let new_name: String = old_name.replace(&old_version, &version);
key.set_value("DisplayName", &new_name).unwrap();
key.set_value("DisplayVersion", version).unwrap();
println!("====== After ======");
let sz_val: String = key.get_value("DisplayName").unwrap();
println!("DisplayName = {}", sz_val);
let sz_val: String = key.get_value("DisplayVersion").unwrap();
println!("DisplayVersion = {}", sz_val);
}
写在最后,使用regedit
包方便很多,不用编译,也许再琢磨一下可以解决打包asar后报错的问题,先用它试试,可能我的环境导致的问题,以后有时间再看