From 12c6223178116b2b0d6271e1ffb6f9d705ec65d7 Mon Sep 17 00:00:00 2001 From: yuejiajun <1530620364@qq.com> Date: Fri, 15 Aug 2025 11:47:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=8C=85=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/install_base.iss | 362 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 base/install_base.iss diff --git a/base/install_base.iss b/base/install_base.iss new file mode 100644 index 0000000..c09c663 --- /dev/null +++ b/base/install_base.iss @@ -0,0 +1,362 @@ +;iss + +#define MyAppName "基础环境" +#define MyAppVersion "v1.0.0" +#define MyAppPublisher "X" +#define MyAppURL "~" +#define MyAppExeName "command" +#define MyAppAssocName MyAppName + " File" +#define MyAppAssocExt ".myp" +#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt + + +; 默认配置 +[Setup] +AppId={{517C2278-C7C9-43D0-8E94-BFD2039C7BB8} +; 默认安装路径 +DefaultDirName={localappdata}\XManage +; 是否加密 +;Encryption=yes +; 安装密码 +;Password=20250801 +; ICO图标 +; SetupIconFile=Resources\startup.ico +UninstallFilesDir={app} +UninstallDisplayIcon={app}\{#MyAppExeName}.exe +VersionInfoCompany= +VersionInfoCopyright=CopyRight © 2025 +VersionInfoDescription= +VersionInfoProductVersion=1.0.0 +VersionInfoProductName=基础环境(支持Windows7及以上) + +; 默认配置 +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +ChangesAssociations=yes +DisableDirPage=no +DisableProgramGroupPage=no +Compression=lzma2 +SolidCompression=yes +WizardStyle=modern +ChangesEnvironment=yes +PrivilegesRequired=admin +ArchitecturesAllowed=x64compatible +ArchitecturesInstallIn64BitMode=x64compatible +OutputDir=Release\ +OutputBaseFilename=Setup-{#MyAppVersion} + + +; 语言选择 +[Languages] +Name: "Chinese"; MessagesFile: "compiler:Languages\Chinese.isl" + + +;; 组件安装方式 +[Types] +Name: "full"; Description: "完整组件安装" +Name: "custom"; Description: "自定义组件安装" + + +;; 组件列表选择项 +[Components] +Name: "MainApp"; Description: "{#MyAppName}主程序"; Types: full; Flags: checkablealone fixed +Name: "JDK"; Description: "JDK程序"; Types: full custom +Name: "Redis"; Description: "Redis程序"; Types: full custom +Name: "MinIO"; Description: "MinIO程序"; Types: full custom +Name: "RocketMQ"; Description: "RocketMQ程序"; Types: full custom +Name: "Nginx"; Description: "Nginx程序"; Types: full custom +Name: "MySQL"; Description: "MySQL程序"; Types: full custom + + +;; 引入文件列表 +[Files] +;; Readme +Source: "Resources\Readme.md"; DestDir: "{app}"; Flags: isreadme +;; 文件 +Source: "Resources\grep.exe"; DestDir: "{app}\usr"; DestName: "grep.exe"; Flags: ignoreversion; Components: MainApp +;; 文件夹 +Source: "Resources\usr\*"; DestDir: "{app}\usr\"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: MainApp +Source: "Resources\jdk\*"; DestDir: "{app}\jdk\"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: JDK +Source: "Resources\redis\*"; DestDir: "{app}\redis\"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs; Components: Redis +Source: "Resources\io\*"; DestDir: "{app}\io\"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs; Components: MinIO +Source: "Resources\rocketmq\*"; DestDir: "{app}\rocketmq\"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs; Components: RocketMQ +Source: "Resources\nginx\*"; DestDir: "{app}\nginx\"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs; Components: Nginx +Source: "Resources\mysql\*"; DestDir: "{app}\mysql\"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs; Components: MySQL + + +;; 创建必要目录 +[Dirs] +Name: "{app}\nginx\dist"; Permissions: users-modify + + +;; 安装前后删除文件 +[InstallDelete] +Type: files; Name: "{app}\mysql\template*.bat"; +Type: files; Name: "{app}\mysql\start-mysql-demo.bat"; +Type: files; Name: "{app}\mysql\template.ini"; + + +;; 安装时注册表与环境变量列表 +[Registry] +; 写入普通注册表项 +Root: HKLM; Subkey: "Software\X\Command"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"; Flags: uninsdeletekey +Root: HKLM; Subkey: "Software\X\Command"; ValueType: string; ValueName: "Version"; ValueData: "{#SetupSetting("AppVersion")}" + +; 默认注册信息 +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName}.exe,0" +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}.exe"" ""%1""" + +;; 【grep、awk、sed、rar、zip、tar...】(通用服务) +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MainApp; \ + ValueName: "X_COMMAND"; ValueData: "{app}"; +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MainApp; \ + ValueName: "Path"; ValueData: "{olddata};%X_COMMAND%\usr"; Check: NeedsAddPath('%X_COMMAND%\usr'); + + + +; 【Java】追加到 PATH 变量 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: JDK; \ + ValueName: "Path"; ValueData: "{olddata};%JAVA_HOME%\bin"; Check: NeedsAddPath('%JAVA_HOME%\bin'); +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: JDK; \ + ValueName: "JAVA_HOME"; ValueData: "{app}\jdk"; +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: JDK; \ + ValueName: "JDK_21"; ValueData: "{app}\jdk"; + + + +; 【Redis】追加到 PATH 变量 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: Redis; \ + 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; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MinIO; \ + 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; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: Nginx; \ + ValueName: "Path"; ValueData: "{olddata};%X_COMMAND%\nginx"; Check: NeedsAddPath('%X_COMMAND%\nginx'); + + + +; 【RocketMQ】追加到 PATH 变量 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: RocketMQ; \ + ValueName: "ROCKETMQ_HOME"; ValueData: "{app}\rocketmq"; Check: CheckRegistryPath('{app}\rocketmq'); +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: RocketMQ; \ + ValueName: "ROCKETMQ_SBIN"; ValueData: "{app}\rocketmq\sbin"; +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: RocketMQ; \ + ValueName: "Path"; ValueData: "{olddata};%ROCKETMQ_SBIN%"; Check: NeedsAddPath('%ROCKETMQ_SBIN%'); + + + +; 【MySQL】环境变量(注册服务使用) +; 数据库服务注册后服务名 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MySQL; \ + ValueName: "X_MANAGE_DB_SC"; ValueData: "x_database"; +; 这两个值,将作为后续判断程序是否已经安装做依据 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MySQL; \ + ValueName: "X_MANAGE_DB_EXE"; ValueData: "{app}\mysql\bin\mysqld.exe"; +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MySQL; \ + ValueName: "X_MANAGE_DB_COF"; ValueData: "{app}\mysql\my.ini"; + +; MySQL(通用服务),导入脚本数据使用 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MySQL; \ + ValueName: "X_COMMAND_MYSQL"; ValueData: "{app}\mysql\"; +; 追加到 PATH 变量 +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; Flags: preservestringtype; AfterInstall: RefreshEnvironment; Components: MySQL; \ + ValueName: "Path"; ValueData: "{olddata};%X_COMMAND_MYSQL%\bin"; Check: NeedsAddPath('%X_COMMAND_MYSQL%\bin'); + + +;; 自定义函数 +[Code] + +const + WM_SETTINGCHANGE = 26; // 0x001A 的十进制 + SMTO_ABORTIFHUNG = 2; // 0x0002 的十进制 + + +function SendMessageTimeout( + hWnd: Integer; + Msg: Integer; + wParam: Integer; + lParamStr: String; + fuFlags: Integer; + uTimeout: Integer; + var lpdwResult: Integer +): Integer; +external 'SendMessageTimeoutW@user32.dll stdcall'; + + +// 给 Path 系统环境变量追加环境 +function NeedsAddPath(Param: string): boolean; +var + OrigPath: string; +begin + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, + 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', + 'Path', OrigPath) + then begin + Result := True; + exit; + end; + // 检查路径是否已存在 + Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0; + if Result = True then + Result := Pos(';' + Param + '\;', ';' + OrigPath + ';') = 0; +end; + + +// 刷新系统环境 +procedure RefreshEnvironment; +var + Res: Integer; +begin + SendMessageTimeout( + HWND_BROADCAST, + WM_SETTINGCHANGE, + 0, + 'Environment', + SMTO_ABORTIFHUNG, + 5000, + Res + ); +end; + + +// 检查环境变量,路径是否存在空格 +function CheckRegistryPath(Path: string): Boolean; +begin + if Pos(' ', Path) > 0 then + begin + SuppressibleMsgBox('安装程序错误: 检测到无效的注册表路径 "' + Path + '"。路径不能包含空格。', mbCriticalError, MB_OK, IDOK); + Abort; + Result := False; + Exit; + end; + Result := True; +end; + + +// 以 UTF-8 写入文件 +function SaveStringToUTF8File(const FileName, Content: String; Append: Boolean): Boolean; +var + UTF8Content: AnsiString; +begin + UTF8Content := UTF8Encode(Content); + Result := SaveStringToFile(FileName, UTF8Content, Append); +end; + + +// 从模板创建配置文件 +procedure CreateConfigFromTemplate; +var + // ini + TemplateIniPath: String; + TargetIniPath: String; + // initial + TemplateInitialPath: String; + TargetInitialPath: String; + // register + TemplateRegisterPath: String; + TargetRegisterPath: String; + // handle params + ConfigLines: TArrayOfString; + I: Integer; + ReplaceCount: Integer; +begin + + // generate my.ini + TemplateIniPath := ExpandConstant('{app}\mysql\template.ini'); + TargetIniPath := ExpandConstant('{app}\mysql\my.ini'); + + if LoadStringsFromFile(TemplateIniPath, ConfigLines) then + begin + for I := 0 to GetArrayLength(ConfigLines)-1 do + begin + StringChangeEx(ConfigLines[I], '%INSTALLPATH%', ExpandConstant('{app}\mysql'), True); + StringChangeEx(ConfigLines[I], '%DATAPATH%', ExpandConstant('{app}\mysql\data'), True); + StringChangeEx(ConfigLines[I], '\', '\\', True); + end; + + SaveStringsToFile(TargetIniPath, ConfigLines, False); + end; + + + + // generate initialize-and-start-mysql.bat + TemplateInitialPath := ExpandConstant('{app}\mysql\template-initialize-and-start-mysql.bat'); + TargetInitialPath := ExpandConstant('{app}\mysql\initialize-and-start-mysql.bat'); + + if LoadStringsFromFile(TemplateInitialPath, ConfigLines) then + begin + for I := 0 to GetArrayLength(ConfigLines)-1 do + begin + StringChangeEx(ConfigLines[I], '%INSTALLPATH%', ExpandConstant('{app}\mysql'), True); + end; + + SaveStringsToFile(TargetInitialPath, ConfigLines, False); + end; + + + + // generate register-mysql-with-data.bat + TemplateRegisterPath := ExpandConstant('{app}\mysql\template-register-mysql-with-data.bat'); + TargetRegisterPath := ExpandConstant('{app}\mysql\register-mysql-with-data.bat'); + + if LoadStringsFromFile(TemplateRegisterPath, ConfigLines) then + begin + for I := 0 to GetArrayLength(ConfigLines)-1 do + begin + StringChangeEx(ConfigLines[I], '%INSTALLPATH%', ExpandConstant('{app}\mysql'), True); + end; + + SaveStringsToFile(TargetRegisterPath, ConfigLines, False); + end; +end; + + +// 在安装完成后执行 +procedure CurStepChanged(CurStep: TSetupStep); +begin + if CurStep = ssPostInstall then + begin + CreateConfigFromTemplate; + + // if UsingWinNT then + // Exec('cmd.exe', '/C cmd', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); + end; +end; + + +// 卸载前先停止程序运行 +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +begin + if CurUninstallStep = usUninstall then begin + // 在这里执行你的脚本或程序 + // Exec(ExpandConstant('{cmd}'), '/C "uninstall_script.bat"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); + end; +end; + + +[UninstallRun] +;; 卸载前运行 +Filename: "sc"; Parameters: "stop redis"; Flags: runascurrentuser runhidden waituntilterminated +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 + + +;; 卸载时删除的文件 +[UninstallDelete] +Type: files; Name: "{app}\mysql\my.ini" +Type: files; Name: "{app}\mysql\*.bat" +Type: filesandordirs; Name: "{app}\mysql\data"