【关于修改注册表信息,设置软件为默认应用,实现查看器功能】

关于修改注册表信息,设置软件为默认应用


前言

实现图片鼠标右键增加自定义可执行软件打开方式,增加图片查看器等功能,以及修改电脑的默认应用程序。
涉及修改打包应用程序.bat文件,修改电脑注册表信息

一、实现鼠标右键增加自定义应用

riteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}" "" "通过${PRODUCT_NAME}打开"
WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}" "icon" "$INSTDIR\logo.ico"
WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}" "MultiSelectModel" "Single"
WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}\command" "" '"$INSTDIR\${EXE_NAME}" "%1" "Preview"'

释义:在 Windows 中使用 NSIS(Nullsoft Scriptable Install System)脚本语言写的注册表操作。

WriteRegStr HKCR “SystemFileAssociations\image\shell${URL_NAME}” “”
“通过 ${PRODUCT_NAME}打开”

这行代码将注册表项 HKCR\SystemFileAssociations\image\shell${URL_NAME} 下的默认值(空字符串)设置为 “通过${PRODUCT_NAME}打开”。这通常用于定义文件关联的操作。
2.

WriteRegStr HKCR “SystemFileAssociations\image\shell${URL_NAME}”
“icon” “$INSTDIR\logo.ico”

这行代码将注册表项 HKCR\SystemFileAssociations\image\shell${URL_NAME} 下的键名为 “icon” 的值设置为 $INSTDIR\logo.ico,表示使用 $INSTDIR\logo.ico 文件作为关联文件的图标。
3.

WriteRegStr HKCR “SystemFileAssociations\image\shell${URL_NAME}”
“MultiSelectModel” “Single”

这行代码将注册表项 HKCR\SystemFileAssociations\image\shell${URL_NAME} 下的键名为 “MultiSelectModel” 的值设置为 “Single”,指定文件的选择模式为单选模式。
4.

WriteRegStr HKCR
“SystemFileAssociations\image\shell${URL_NAME}\command” “”
‘“$INSTDIR${EXE_NAME}” “%1” "Preview’"

这行代码将注册表项 HKCR\SystemFileAssociations\image\shell${URL_NAME}\command 下的默认值(空字符串)设置为 ‘“$INSTDIR${EXE_NAME}” “%1” “Preview”’。这通常用于定义打开文件的命令,其中 $INSTDIR${EXE_NAME} 表示安装目录下的可执行文件,“%1” 表示要打开的文件路径参数,“Preview” 是传递给可执行文件的参数。

提示:总的来说,这些代码片段用于配置文件关联的操作、图标显示、选择模式以及打开文件的命令,以便在系统中正确地处理特定类型的文件。:

示例

1. 在打包执行文件中添加相应变量(在package.bat执行文件中添加)

:: 安装NSI中所需参数
@set PRODUCT_NAME=图片查看器
@set PRODUCT_VERSION=%GIT_TAG_NAME:~1%
@set PRODUCT_PUBLISHER=软甲归属
@set EXE_NAME=PhotoEditor.exe
@set INSTALL_DIR=MyApp
@set URL_NAME=PhotoEditor
@set PRODUCT_WEB_SITE=https://www.myappcom
SET MAINEXE_FILENAME=PhotoEditor

2. 在nsi打包文件中加入执行命令(package_HuDunPhotoEA.nsi)
Section -Post
  WriteUninstaller "$INSTDIR\uninst.ep"
  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${EXE_NAME}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\logo.ico"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
  WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}" "" "通过${PRODUCT_NAME}打开"
	WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}" "icon" "$INSTDIR\logo.ico"
	WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}" "MultiSelectModel" "Single"
  WriteRegStr HKCR "SystemFileAssociations\image\shell\${URL_NAME}\command" "" '"$INSTDIR\${EXE_NAME}" "%1" "Preview"'
SectionEnd
3.在electron的主窗口main.js中增加查看器子窗口
const { app,BrowserWindow,Menu,globalShortcut,screen,protocol,Tray} = require('electron')
let win = null
let tray = null
let winURL = null
let childWin = null
let group = []
let ishide = false;
let index = 0
let process = require('process')
let userInfo = {}

// 添加数据
function addRegData(path, type) {
	if (type == "Preview") global.previewPath.push(path);
	else {
		global.imgPath[type].push(path);
		// 将其他的清空
		for (let key in global.imgPath) {
			if (key != type) global.imgPath[key] = [];
		}
		global.imgType = type;
	}
}

/**
 * 查看器子窗口
 * @childWin 存在有多个子窗口时
 * @group  一个数组对象,[childWin1,childWin2...]
 * @Preview  子窗口的显示路径url,此处的命名Preview应与打包配置文件中传递给可执行文件的参数一致
 */
function openChildWindow() {
  childWin ={
    id:index,
    obj:null,
  }
	let newWinConfig = JSON.parse(JSON.stringify(winConfig));
	newWinConfig.title = "图片助手——查看";
	// newWinConfig.parent = win;  // 还是平级的吧
	newWinConfig.resizable = true; // 窗口可以拖动
	childWin.obj = new BrowserWindow(newWinConfig);
	remote.enable(childWin.obj.webContents);
	if (/xunjietupian/.test(winURL)) {//正式环境
		chooseDomain([
			"photo-pc.aaa.com",
			"photo-pc.aaa1.com",//是否有多个域名
		]).then((res) => {
			childWin.obj.loadURL(
				"https://" +
					res +
					"/5.4.0.0/?ran=" +
					new Date().getTime() +
					"#/" +
					"Preview"
			);
		});
	} else {
		if (/9900/.test(winURL)) {//本地环境
			childWin.obj.loadURL(winURL + "#/" + "Preview"); // hash路由
		} else {
			console.log(
				winURL + "/5.4.0.0/?ran=" + new Date().getTime() + "#/" + "Preview"
			);
			childWin.obj.loadURL(
				winURL + "/5.4.0.0/?ran=" + new Date().getTime() + "#/" + "Preview"
			); // hash路由
		}
	}
	// // 在加载页面时,渲染进程第一次完成绘制时
	childWin.obj.once("ready-to-show", () => {
		console.log("显示");
    setTimeout(() => {
      childWin.obj.show();
		  childWin.obj.focus();
    }, 350);
		
	});
  //设置调试环境
	globalShortcut.register("Alt+F11", () => {
    console.log(childWin,'====childWin-------');
		childWin.obj.webContents.openDevTools();
	});
	childWin.obj.on("closed", () => {
		childWin.obj = null;
	});
	childWin.obj.webContents.on("did-finish-load", () => {
		childWin.obj.webContents.send("refreshfilearg",global.previewPath[index],index);
    //子进程与主进程同步所需要的信息
		childWin.obj.webContents.send("dataChanged",userInfo);
    index++
	});
  group.push(childWin)
  console.log(group,'=======group');
}
// 主窗口托盘处理
function setTray() {
	const trayMenuTemplate = [
		{
			label: "打开窗口",
			click: () => {
				win.show();
				if (tray) {
					tray.destroy();
					tray = null;
					ishide=false;
				}
			},
		},
		{
			label: "退出",
			click: () => {
				win.destroy();
				win = null;
			},
		},
	];
	// 创建托盘实例
	if (tray == null) tray = new Tray(ICO_PATH);
	// 图标的上下文菜单
	const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
	// 隐藏主窗口
	win.hide();
	// 设置托盘悬浮提示
	tray.setToolTip("图片助手");
	// 设置托盘菜单
	tray.setContextMenu(contextMenu);
	// 单机托盘小图标显示应用
	tray.on("click", function () {
		// 显示主程序
		win.show();
		ishide=false;
		// 关闭托盘显示
		if (tray) {
			tray.destroy();
			tray = null;
		}
	});
}
// 创建浏览器窗口
function createWindow() {
  global.previewPath = []; //预览
  global.imgType = ""; // 会记录最近的一次操作
  if (process.argv && process.argv[2]) {
    // 储存数据,用对象方式,多张图片。软件第一次运行,可能还没有实例完。
    addRegData(process.argv[1], process.argv[2]);
    // 开始加载子窗口
    if (process.argv[2] == "Preview") {
      ishide = true;
      openChildWindow();
    }
  }
  getSdkPath();
  win = win != null ? win.show() : new BrowserWindow({
    width: 1170,
    height: 726,
    minWidth: 1024,
    minHeight: 580,
    show: false,
    resizable: true,
    maximizable: true,
    fullscreenable: true,
    icon: ICO_PATH,
    center: true,
    titleBarStyle: "hidden",
    title: "图片编辑助手",
    // transparent:true,
    //MAC_OS
    simpleFullscreen: true,
    //no border
    frame: false,
    webPreferences: {
      webSecurity: false,//设置无法读取到本地文件图片问题,解决electron的跨域问题
      contextIsolation: false,
      nodeIntegration: true,
      enableRemoteModule: true,
      webviewTag: true,
    }
  })
}
4.在vue文件中加入需要展示的页面,接受主进程传递的消息

[(vue中src–>views–>Preview)]

created() {
    window.asd = this;
    ipcRenderer.on("refreshfilearg", (e, data,index) => {
      this.imgPreviewId = index
      console.log("开始显示");
      ipcRenderer.send("showChildWeb");
      // 处理data中的图片信息
      this.imgInit(data);
    });
  },
}

以上就可以实现在图片上点击鼠标右键打开软件了
在这里插入图片描述

二、将电脑的默认软件修改为自己的软件,修改注册表信息

方法1.使用注册表文件(注册表文件需自己编写)

1.创建一个regFolder文件夹,其中包括open.reg文件和delete.reg文件

open.reg

代码如下(示例):

Windows Registry Editor Version 5.00
//将.pdf格式文件的打开方式修改为PhotoEditor的应用,用于关联
[HKEY_CLASSES_ROOT\.pdf]
@="PhotoEditor"
//添加默认应用的打开路径
[HKEY_CLASSES_ROOT\PhotoEditor\shell\open\command]
@="${install} \"%1\" \"Preview\""
//删除原有的默认应用的设置参数
[-HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pdf\UserChoice]
//增加的默认应用的设置参数
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pdf\UserChoice]
"Hash"="mRngFltqE1c="
"ProgId"="PhotoEditor"
//系统将会删除注册表中名为 MSEdgePDF 的项及其下的所有子项,从而清除相关的注册表配置信息。此句可不要
[-HKEY_CLASSES_ROOT\MSEdgePDF]
  • ${install}:为应用软件的安装路径,应动态获取。例如:

[HKEY_CLASSES_ROOT\PhotoEditor\shell\open\command]
@=“C:\ProgramData\HuDunPhotoEA\PhotoEditor.exe “%1” “Preview””

  • “ProgId”:为应用的名称
  • HKEY_CLASSES_ROOT 是注册表中的一个根键,包含了文件关联和对象类别的信息。
delete.reg

代码如下(示例):

Windows Registry Editor Version 5.00
//取消注册表的文件关联
[-HKEY_CLASSES_ROOT\SystemFileAssociations\.pdf\shell]
调用方式
//roamingPath为存放注册表文件的路径
function readReg(fileName){
	let regFile = path.join(roamingPath, "../regFolder", fileName);
	console.log("文件路径----", regFile);
	return new Promise((resolve, reject) => {
		fs.readFile(regFile, (werr, data) => {
			if (werr) {
				return reject(werr);
			}
			let regData = iconv.decode(data, "gbk");
			if (regData.indexOf("${install}") > -1 || regData.indexOf("${install2}") > -1) {
				regData = regData.replaceAll(
					"${install}",
					path.join(window.process.argv[0]).replace(/[\/\\]/g, "\\\\")
				);
				regData = regData.replaceAll(
					"${install2}",
					path.join(window.process.argv[0], "../icon").replace(/[\/\\]/g, "\\\\")
				);
				regData = iconv.encode(regData, "gbk");
				fs.writeFile(regFile, regData, (err) => {
					if (err) {
						reject(err);
					}
					exec(`regedit /s "${regFile}"`, (err, stdout, stderr) => {
						if (err || stderr) {
							console.error(err);
							resolve(false);
						} else {
							resolve(true);
						}
					});
				});
			} else {
				exec(`regedit /s "${regFile}"`, (err, stdout, stderr) => {
					if (err || stderr) {
						console.error(err);
						resolve(false);
					} else {
						resolve(true);
					}
				});
			}
		});
	});
}
readReg("open.reg");

方法2.调用c++提供的dll

需要有对应的dll可调用。调用方式根据所提供的方式来
代码如下(示例):

const dllPath = path.join(mainPath, '../dll/SetDefaultTool.dll')

const winDll = new ffi.Library(dllPath,{
    WriteUserChoice: [ref.types.bool, [refArray(ref.types.uint16), refArray(ref.types.uint16)]],
    DeleteUserChoice: [ref.types.bool, [refArray(ref.types.uint16)]],
})
/**
 * 写入注册表信息方法
 * @param {*} key 修改的格式
 * @param {*} value 需要修改成的软件名称
 */
writeUserChoice = (key, value='PhotoEditor') => {
    // const keyBuffer = Buffer.from(key)
    // const valueBuffer = Buffer.from(value)
    // const res = winDll.WriteUserChoice(keyBuffer, valueBuffer)
    const keyCodes = new refArray(ref.types.uint16)(256)
    for(let i=0; i< key.length; i++) {
      keyCodes[i] = key.charCodeAt(i)
    }

    const valueCodes = new refArray(ref.types.uint16)(256)
    for(let i=0; i< value.length; i++) {
        valueCodes[i] = value.charCodeAt(i)
    }
    
     const res = winDll.WriteUserChoice(keyCodes.buffer, valueCodes.buffer)
     //返回true or false
}

writeUserChoice('.png')

问题

提示:这里对文章进行总结:

1.调用成功后,双击图片并未使用设置的软件打开图片

以上两种方式都存在,虽然调用成功了,但是在修改时系统会弹出提示弹窗
在这里插入图片描述
原因:其实我们已经修改成功了,但是又被系统改回去了,导致失败。

有些常用格式,有其它多个应用抢占的时候,电脑系统就是会自动把设置的给你删掉,并不是所有格式都能一次性成功修改,这个时候可以尝试在修改时多次调用执行修改的命令。

2.注册表信息已经修改成功,且在系统注册表中也可查看到设置的对应信息,但是双击图片时又被修改为之前的默认应用了

  • 首先在文件执行成功后,打开注册表查看是否修改成功
    在这里插入图片描述
    但是在双击图片打开这里的值就自动修改为之前的默认应用了
    原因:未关联注册表信息。
    在这里插入图片描述
    前面设置的这段代码就是在关联注册表,仅仅是修改注册表的UserChoice的配置修改并不能将应用设置未默认的。在默认应用的选择列表中并不会出现设置的应用

//将.pdf格式文件的打开方式修改为PhotoEditor的应用,用于关联
[HKEY_CLASSES_ROOT.pdf]
@=“PhotoEditor”
//添加默认应用的打开路径
[HKEY_CLASSES_ROOT\PhotoEditor\shell\open\command]
@=“${install} “%1” “Preview””
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值