绿色包,mysql处理成即用即启,而非服务的形式,因为注册服务需要管理员身份

This commit is contained in:
2025-12-01 13:48:03 +08:00
parent 7d95a869c1
commit f8be28077f
3 changed files with 262 additions and 651 deletions

View File

@@ -67,7 +67,6 @@ class Lifecycle {
this.mysqlPort = null;
this.javaPort = null;
this.autoRefreshTimer = null;
this.isRestartingForAdmin = false; // 权限提升重启标记
}
/**
@@ -119,23 +118,8 @@ class Lifecycle {
this.startupManager.updateProgress('wait-mysql', { mysqlPort: this.mysqlPort });
await this.sleep(500);
} catch (error) {
logger.error('[lifecycle] MySQL service error:', error);
this.logWindowManager.addLog('error', `MySQL 服务错误: ${error.message}`);
// 检查是否是权限问题
if (error.message && (error.message.includes('administrator') || error.message.includes('Denied'))) {
logger.error('[lifecycle] Need administrator privileges');
this.logWindowManager.addLog('error', '检测到需要管理员权限来安装 MySQL 服务');
this.logWindowManager.addLog('system', '应用将自动请求管理员权限并重启...');
// 等待用户看清日志
await this.sleep(2000);
// 自动以管理员身份重启应用
await this.restartAsAdmin();
// 退出当前实例
return;
}
logger.error('[lifecycle] MySQL error:', error);
this.logWindowManager.addLog('error', `MySQL 错误: ${error.message}`);
throw error;
}
}
@@ -350,12 +334,6 @@ class Lifecycle {
async cleanup() {
logger.info('[lifecycle] Starting cleanup...');
// 如果是权限提升重启,跳过清理(服务需要继续运行)
if (this.isRestartingForAdmin) {
logger.info('[lifecycle] Restarting for admin, skip cleanup');
return;
}
// 清除自动刷新定时器
if (this.autoRefreshTimer) {
clearTimeout(this.autoRefreshTimer);
@@ -397,10 +375,26 @@ class Lifecycle {
}
}
// MySQL 作为Windows服务运行应用关闭时保持运行
logger.info('[lifecycle] MySQL service keeps running as Windows service');
// 停止 MySQL 进程(进程模式)
if (this.mysqlServiceManager) {
try {
logger.info('[lifecycle] Stopping MySQL process...');
if (this.logWindowManager && this.logWindowManager.logWindow && !this.logWindowManager.logWindow.isDestroyed()) {
this.logWindowManager.addLog('system', '正在停止 MySQL...');
}
await this.mysqlServiceManager.stopMySQLProcess();
logger.info('[lifecycle] MySQL process stopped');
if (this.logWindowManager && this.logWindowManager.logWindow && !this.logWindowManager.logWindow.isDestroyed()) {
this.logWindowManager.addLog('success', 'MySQL 已停止');
}
} catch (error) {
logger.error('[lifecycle] Failed to stop MySQL:', error);
}
}
if (this.logWindowManager && this.logWindowManager.logWindow && !this.logWindowManager.logWindow.isDestroyed()) {
this.logWindowManager.addLog('system', 'MySQL 服务保持运行');
this.logWindowManager.addLog('system', '清理完成,应用即将退出');
this.logWindowManager.addLog('system', '='.repeat(60));
}
@@ -485,72 +479,6 @@ class Lifecycle {
}
}
/**
* 以管理员身份重启应用
*/
async restartAsAdmin() {
const { app, dialog } = require('electron');
const { spawn } = require('child_process');
const path = require('path');
logger.info('[lifecycle] Requesting administrator privileges...');
try {
// 显示提示对话框
await dialog.showMessageBox({
type: 'warning',
title: '告警',
message: '需要管理员权限',
buttons: ['确定']
});
// 用户点击确定,以管理员身份重启
// 获取应用可执行文件路径
const exePath = app.getPath('exe');
logger.info('[lifecycle] Restarting with admin privileges:', exePath);
// 使用 PowerShell 以管理员身份启动
const psCommand = `Start-Process -FilePath "${exePath}" -Verb RunAs`;
const child = spawn('powershell.exe', ['-Command', psCommand], {
detached: true,
stdio: 'ignore',
windowsHide: true
});
// 分离子进程,父进程退出不影响子进程
child.unref();
// 立即退出当前实例,释放单实例锁
// 必须立即退出,否则新实例会因为单实例锁无法启动
logger.info('[lifecycle] Quitting current instance to release lock...');
// 设置标记,跳过清理流程(这只是重启,不是真正退出)
this.isRestartingForAdmin = true;
// 关闭所有窗口
const BrowserWindow = require('electron').BrowserWindow;
BrowserWindow.getAllWindows().forEach(win => {
try {
win.destroy();
} catch (e) {
// 忽略错误
}
});
// 立即强制退出,释放锁
process.exit(0);
} catch (error) {
logger.error('[lifecycle] Failed to restart as admin:', error);
this.logWindowManager.addLog('error', '自动提升权限失败,请手动以管理员身份运行');
// 等待5秒后关闭
await this.sleep(5000);
app.quit();
}
}
/**
* 睡眠函数
*/
@@ -558,24 +486,6 @@ class Lifecycle {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* 检查是否有管理员权限(仅 Windows
*/
checkAdminPrivileges() {
if (process.platform !== 'win32') {
return true; // 非 Windows 系统不需要检查
}
try {
const { execSync } = require('child_process');
// 尝试执行需要管理员权限的命令
execSync('net session', { stdio: 'ignore' });
return true;
} catch (error) {
return false;
}
}
/**
* electron app ready
*/
@@ -589,16 +499,7 @@ class Lifecycle {
async windowReady() {
logger.info('[lifecycle] window-ready hook triggered');
// 在创建任何窗口之前,先检查管理员权限
const hasAdminPrivileges = this.checkAdminPrivileges();
logger.info('[lifecycle] Has admin privileges:', hasAdminPrivileges);
if (!hasAdminPrivileges) {
logger.warn('[lifecycle] No admin privileges, requesting elevation');
// 调用已有的 restartAsAdmin 方法,避免代码重复
await this.restartAsAdmin();
return; // 阻止后续代码执行
}
// 进程模式不需要管理员权限检查
// 创建日志管理器(但不显示窗口,仅用于写日志文件)
logger.info('[lifecycle] Creating log window manager...');