diff --git a/base/Resources/rocketmq/sbin/rocketmq.bat b/base/Resources/rocketmq/sbin/rocketmq.bat index a2ff8c3..0d586e4 100644 --- a/base/Resources/rocketmq/sbin/rocketmq.bat +++ b/base/Resources/rocketmq/sbin/rocketmq.bat @@ -72,16 +72,16 @@ if exist "%ROCKETMQ_HOME%\bin\rocketmq-dashboard.jar" ( start "RocketMQ Dashboard" /B cmd /c ""%JAVA_HOME%\bin\java" -jar -Dserver.port=8088 "%ROCKETMQ_HOME%\bin\rocketmq-dashboard.jar"" ) -echo. -echo ======================================== -echo RocketMQ Services Status -echo ======================================== -echo - NameServer (Port: 9876) -echo - Broker (Port: 10911) -echo - Proxy (Port: 8081) -echo - Dashboard (Port: 8080) -echo ======================================== -echo. +:: echo. +:: echo ======================================== +:: echo RocketMQ Services Status +:: echo ======================================== +:: echo - NameServer (Port: 9876) +:: echo - Broker (Port: 10911) +:: echo - Proxy (Port: 8081) +:: echo - Dashboard (Port: 8080) +:: echo ======================================== +:: echo. exit /b 0 diff --git a/base/Resources/usr/unrar.exe b/base/Resources/usr/unrar.exe index 40a80e5..2611148 100644 Binary files a/base/Resources/usr/unrar.exe and b/base/Resources/usr/unrar.exe differ diff --git a/base/install_all.iss b/base/install_all.iss index 3a08cca..3690485 100644 --- a/base/install_all.iss +++ b/base/install_all.iss @@ -1,7 +1,7 @@ ;iss #define MyAppName "基础环境" -#define MyAppVersion "1.0.8" +#define MyAppVersion "1.0.12" #define MyAppPublisher "X" #define MyAppURL "~" #define MyAppExeName "command" @@ -54,7 +54,7 @@ PrivilegesRequired=admin ArchitecturesAllowed=x64compatible ArchitecturesInstallIn64BitMode=x64compatible OutputDir=Release\ -OutputBaseFilename=Setup-{#MyAppVersion} +OutputBaseFilename=RuntimeSetup-{#MyAppVersion} ; 语言选择 @@ -73,7 +73,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{ ;; 程序 ICO [Icons] ;Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}.exe" -Name: "{autodesktop}\Quick Start Environment"; Filename: "{app}\quick.bat"; Tasks: desktopicon +Name: "{autodesktop}\Quick Start Environment"; Filename: "{app}\quick.bat"; Comment: "一键启动 Redis、MinIO、Home、RocketMQ 服务"; Tasks: desktopicon ;; 组件安装方式 @@ -125,7 +125,7 @@ Name: "{app}\nginx\logs"; Permissions: users-modify; Components: Nginx; Name: "{app}\nginx\dist"; Permissions: users-modify; Components: Nginx; -;; 安装前后删除文件 +;; 安装前后删除文件(存在不生效的可能,转为 code 实现) [InstallDelete] ;Type: files; Name: "{app}\mysql\template.ini"; ;Type: files; Name: "{app}\mysql\template-initialize-and-start-mysql.bat"; @@ -164,36 +164,45 @@ Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environmen ValueName: "JAVA_HOME"; ValueData: "{app}\jdk"; Flags: uninsdeletevalue ; Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Components: JDK; \ ValueName: "JDK_21"; ValueData: "{app}\jdk"; Flags: uninsdeletevalue ; +; 为了启用 java、jps、jar 命令 Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: JDK; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ ValueName: "Path"; ValueData: "{olddata};%JAVA_HOME%\bin"; Check: NeedsAddPath('%JAVA_HOME%\bin'); + ;; 【Redis】追加到 PATH 变量 -Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: Redis; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ +;Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: Redis; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ ValueName: "Path"; ValueData: "{olddata};%X_COMMAND%\redis"; Check: NeedsAddPath('%X_COMMAND%\redis'); - +; +; 关闭注册到环境变量,整体由一键启动脚本代为执行 ;; 【MinIO】追加到 PATH 变量 -Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: MinIO; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ +;Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: MinIO; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ ValueName: "Path"; ValueData: "{olddata};%X_COMMAND%\io"; Check: NeedsAddPath('%X_COMMAND%\io'); - +; +; 关闭注册到环境变量,整体由一键启动脚本代为执行 ;; 【Nginx】追加到 PATH 变量 -Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: Nginx; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ +;Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: Nginx; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ ValueName: "Path"; ValueData: "{olddata};%X_COMMAND%\nginx"; Check: NeedsAddPath('%X_COMMAND%\nginx'); - +; +; 关闭注册到环境变量,整体由一键启动脚本代为执行 ;; 【RocketMQ】追加到 PATH 变量 +; rocketmq 脚本必要参数 Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Components: RocketMQ; Flags: uninsdeletevalue; \ ValueName: "ROCKETMQ_HOME"; ValueData: "{app}\rocketmq"; Check: CheckRegistryPath('{app}\rocketmq'); -Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Components: RocketMQ; Flags: uninsdeletevalue; \ +;Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Components: RocketMQ; Flags: uninsdeletevalue; \ ValueName: "ROCKETMQ_SBIN"; ValueData: "{app}\rocketmq\sbin"; -Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: RocketMQ; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ +;Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: RocketMQ; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ ValueName: "Path"; ValueData: "{olddata};%ROCKETMQ_SBIN%"; Check: NeedsAddPath('%ROCKETMQ_SBIN%'); +; +; 关闭注册到环境变量,整体由一键启动脚本代为执行 + @@ -206,11 +215,15 @@ Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environmen ValueName: "X_MANAGE_DB_EXE"; ValueData: "{app}\mysql\bin\mysqld.exe"; ;Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Components: MySQL; Flags: uninsdeletevalue ; AfterInstall: RefreshEnvironment; \ ValueName: "X_MANAGE_DB_COF"; ValueData: "{app}\mysql\my.ini"; +; +; 暂时关闭注册到环境变量,暂时由 bat 启动或直接注册到服务 +; 上述环境变量是 ps1 启动时所需的必要参数,状态暂停,等待整理 + ; MySQL【通用服务】,导入脚本数据使用 Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Components: MySQL; Flags: uninsdeletevalue; \ ValueName: "X_COMMAND_MYSQL"; ValueData: "{app}\mysql\"; -; 追加到 PATH 变量 +; 追加到 PATH 变量,where mysql 语法判定使用 Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Components: MySQL; Flags: preservestringtype; AfterInstall: RefreshEnvironment; \ ValueName: "Path"; ValueData: "{olddata};%X_COMMAND_MYSQL%\bin"; Check: NeedsAddPath('%X_COMMAND_MYSQL%\bin'); @@ -220,12 +233,19 @@ Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environmen [Code] const + // 系统环境变量 WM_SETTINGCHANGE = 26; // 0x001A 的十进制 SMTO_ABORTIFHUNG = 2; // 0x0002 的十进制 // 定义 VC++ 2019 运行时的注册表检查路径 VC2019_REDIST_X64 = '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}'; VC2019_REDIST_X86 = '{422B21A3-06FA-3F2F-A6C6-21BCC9B8E2F3}'; + + // 服务 + SC_MANAGER_CONNECT = $0001; + SERVICE_STOP = $0020; + SERVICE_QUERY_STATUS = $0004; + SERVICE_CONTROL_STOP = $00000001; // 获取安装密码 @@ -243,6 +263,12 @@ begin end; +// 导入 Windows API 函数,作用于 延迟函数 +function GetTickCount: DWord; + external 'GetTickCount@kernel32.dll stdcall'; + + +// 导入 Windows API 函数,作用于 环境变量更新 function SendMessageTimeout( hWnd: Integer; Msg: Integer; @@ -255,6 +281,41 @@ function SendMessageTimeout( external 'SendMessageTimeoutW@user32.dll stdcall'; +// 导入必要的 Windows API 函数,作用于 服务 +function OpenService( + hSCManager: Longword; + lpServiceName: string; + dwDesiredAccess: Longword +): Longword; + external 'OpenServiceW@advapi32.dll stdcall'; + + +// 导入必要的 Windows API 函数,作用于 服务 +function ControlService( + hService: Longword; + dwControl: Longword; + var lpServiceStatus: Longword +): Integer; + external 'ControlService@advapi32.dll stdcall'; + + +// 导入必要的 Windows API 函数,作用于 服务 +function CloseServiceHandle( + hSCObject: Longword +): Integer; + external 'CloseServiceHandle@advapi32.dll stdcall'; + + +// 导入必要的 Windows API 函数,作用于 服务 +function OpenSCManager( + lpMachineName: string; + lpDatabaseName: string; + dwDesiredAccess: Longword +): Longword; + external 'OpenSCManagerW@advapi32.dll stdcall'; + + + // 给 Path 系统环境变量追加环境 function NeedsAddPath(Param: string): boolean; var @@ -345,10 +406,37 @@ begin end; +// 延迟n秒 +procedure Delay(Seconds: Integer); +var + ResultCode: Integer; +begin + Exec(ExpandConstant('{cmd}'), '/C timeout /t ' + IntToStr(Seconds) + ' /nobreak > nul', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); +end; + +// 延迟n毫秒 +procedure DelayMS(MS: Cardinal); +var + T: Cardinal; +begin + T := GetTickCount; + while (GetTickCount - T) < MS do + begin + // 处理消息队列,防止界面冻结 + Sleep(10); + WizardForm.Refresh; + end; +end; +// InitializeSetup 安装程序初始化时 检查系统环境、前置条件 +// InitializeWizard 向导初始化时 自定义界面、预设置 +// CurStepChanged 安装步骤改变时 在特定步骤(如安装前、后)执行自定义操作 +// DeinitializeSetup 安装结束时(无论成功与否) 清理临时文件、最终配置 + + // 从模板创建配置文件 procedure CreateConfigFromTemplate; var @@ -367,7 +455,7 @@ var ReplaceCount: Integer; begin - // generate my.ini + // 生成 my.ini TemplateIniPath := ExpandConstant('{app}\mysql\template.ini'); TargetIniPath := ExpandConstant('{app}\mysql\my.ini'); @@ -385,7 +473,7 @@ begin - // generate initialize-and-start-mysql.bat + // 生成 initialize-and-start-mysql.bat TemplateInitialPath := ExpandConstant('{app}\mysql\template-initialize-and-start-mysql.bat'); TargetInitialPath := ExpandConstant('{app}\mysql\initialize-and-start-mysql.bat'); @@ -401,7 +489,7 @@ begin - // generate register-mysql-with-data.bat + // 生成 register-mysql-with-data.bat TemplateRegisterPath := ExpandConstant('{app}\mysql\template-register-mysql-with-data.bat'); TargetRegisterPath := ExpandConstant('{app}\mysql\register-mysql-with-data.bat'); @@ -427,6 +515,7 @@ function InitializeSetup: Boolean; begin // 默认允许安装继续 Result := True; + // 如果 VC++ 2019 未安装 if not IsVC2019Installed then begin @@ -434,18 +523,31 @@ begin // 中止安装 Result := False; end; + end; // 在安装完成后执行 procedure CurStepChanged(CurStep: TSetupStep); +var + ResultCode: Integer; + Cmd: string; + MySQLPath: string; + UsrPath: string; begin + + // 仅在安装完成后执行 if CurStep = ssPostInstall then begin + + // 创建配置文件 CreateConfigFromTemplate; - + + // DeleteFile + // DelTree + // 删除模版文件 if FileExists(ExpandConstant('{app}\mysql\template.ini')) then DeleteFile(ExpandConstant('{app}\mysql\template.ini')); @@ -458,16 +560,104 @@ begin if FileExists(ExpandConstant('{app}\mysql\import-data-into-mysql-v2.bat')) then DelTree(ExpandConstant('{app}\mysql\import-data-into-mysql-v2.bat'), False, True, False); - end; + + + // 删除默认 Readme.md + if FileExists(ExpandConstant('{app}\io\Readme.md')) then + DeleteFile(ExpandConstant('{app}\io\Readme.md')); + + if FileExists(ExpandConstant('{app}\jdk\Readme.md')) then + DeleteFile(ExpandConstant('{app}\jdk\Readme.md')); + + if FileExists(ExpandConstant('{app}\mysql\Readme.md')) then + DeleteFile(ExpandConstant('{app}\mysql\Readme.md')); + + if FileExists(ExpandConstant('{app}\nginx\Readme.md')) then + DeleteFile(ExpandConstant('{app}\nginx\Readme.md')); + + + + // 通过 mysql 初始化生成的唯一 uuid 判断 mysql 是否已经完成初始化 + if not FileExists(ExpandConstant('{app}\mysql\data\auto.cnf')) then + begin + // 如果没有完成初始化,则判断是否存在 readme.md 文件 即完全没有初始化 + if FileExists(ExpandConstant('{app}\mysql\data\Readme.md')) then + begin + // 如果没有初始化,则删除 readme + DelTree(ExpandConstant('{app}\mysql\data\Readme.md'), False, True, False); + // 初始化 + // 同步 ewWaitUntilTerminated + // 异步 ewNoWait + + Cmd := '/C "' + ExpandConstant('{app}') + '\mysql\initialize-and-start-mysql.bat"'; + if not Exec('cmd.exe', Cmd, '', SW_HIDE, ewNoWait, ResultCode) then + begin + MsgBox('初始化 MySQL 脚本失败', mbError, MB_OK); + end else begin + DelayMS(3000); + DeleteFile(ExpandConstant('{app}\mysql\initialize-and-start-mysql.bat')); + DeleteFile(ExpandConstant('{app}\mysql\register-mysql-with-data.bat')); + end; + + // 存在默认库SQL压缩包 + if FileExists(ExpandConstant('{app}\mysql\database.rar')) then + begin + // 解压 + if not Exec('cmd.exe', '/C " cd ' + ExpandConstant('{app}') + '\mysql && %cd%\..\usr\unrar.exe x database.rar script\demo\"', '', SW_HIDE, ewNoWait, ResultCode) then + begin + MsgBox('初始化 MySQL 脚本失败', mbError, MB_OK); + end; + + // 删除 database.rar 默认库SQL压缩包 + DelayMS(1000); + DelTree(ExpandConstant('{app}\mysql\database.rar'), False, True, False); + + // 判断是否安装了 usr 基础环境 + if FileExists(ExpandConstant('{app}\usr\rar.exe')) then + begin + // 这个时候 `环境变量` 还没开始注册,所以 bat 导入脚本不生效,因此需要指定临时Path环境变量 + // 导出默认库和用户 + if FileExists(ExpandConstant('{app}\mysql\import-data-into-mysql.bat')) then + begin + + // 临时设置 PATH 并执行脚本 + MySQLPath := ExpandConstant('{app}') + '\mysql\bin'; + UsrPath := ExpandConstant('{app}') + '\usr'; + Cmd := '/C "set PATH=' + MySQLPath + '; ' + UsrPath + ';%PATH%' + + ' && cd ' + ExpandConstant('{app}') + '\mysql' + + ' && import-data-into-mysql.bat"' + + ' && exit"'; + + if not Exec('cmd.exe', Cmd, '', SW_HIDE, ewNoWait, ResultCode) then + begin + MsgBox('初始化 MySQL 脚本失败', mbError, MB_OK); + end; + DelayMS(1000); + end; + end; + + end; + end; + end; + + end; // 安装完成后的执行 + + end; // 卸载前先停止程序运行 procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + hSCManager, hService: Longword; + ServiceStatus: Longword; + ResultCode: Integer; + DataDir: string; begin if CurUninstallStep = usUninstall then begin // 在这里执行你的脚本或程序 // Exec(ExpandConstant('{cmd}'), '/C "uninstall_script.bat"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); + end; end; @@ -478,11 +668,22 @@ Filename: "sc"; Parameters: "stop redis"; Flags: runascurrentuser runhidden wait Filename: "sc"; Parameters: "delete redis"; Flags: runascurrentuser runhidden waituntilterminated Filename: "sc"; Parameters: "stop x_database"; Flags: runascurrentuser runhidden waituntilterminated Filename: "sc"; Parameters: "delete x_database"; Flags: runascurrentuser runhidden waituntilterminated +Filename: "taskkill"; Parameters: "-f -im home-web.exe"; Flags: runascurrentuser runhidden waituntilterminated ;; 卸载时删除的文件 [UninstallDelete] +; 删除 mysql 相关内容(停止服务可能需要一定时间,因此删除mysql时可能存在占用问题导致删除失败,需要转到 code 实现) Type: files; Name: "{app}\mysql\my.ini" Type: files; Name: "{app}\mysql\*.bat" Type: filesandordirs; Name: "{app}\mysql\data" +Type: filesandordirs; Name: "{app}\mysql\lib" +Type: filesandordirs; Name: "{app}\mysql\bin" +; 删除 minio 数据 +Type: filesandordirs; Name: "{app}\io" Type: filesandordirs; Name: "{app}\io\data" +; 删除 nginx log +Type: filesandordirs; Name: "{app}\nginx\logs" +; 删除 rocketmq 数据 +Type: filesandordirs; Name: "{app}\rocketmq\sbin\store" +