2025-09-28 17:00:02 +08:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
"""
|
|
|
|
|
|
NSIS 安装包构建脚本
|
|
|
|
|
|
用于创建 GUI 应用程序的Windows安装包
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
import sys
|
|
|
|
|
|
import shutil
|
|
|
|
|
|
import subprocess
|
|
|
|
|
|
import datetime
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
class NSISInstaller:
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self.script_dir = Path(__file__).parent
|
|
|
|
|
|
self.project_root = self.script_dir.parent
|
|
|
|
|
|
self.dist_dir = self.project_root / "dist" / "MultiPlatformGUI"
|
|
|
|
|
|
self.output_dir = self.script_dir / "output"
|
|
|
|
|
|
self.assets_dir = self.script_dir / "assets"
|
|
|
|
|
|
self.nsis_script = self.script_dir / "installer.nsi"
|
|
|
|
|
|
|
|
|
|
|
|
# 应用程序信息
|
|
|
|
|
|
self.app_name = "水滴AI客服智能助手"
|
|
|
|
|
|
self.app_name_en = "ShuiDi AI Assistant"
|
2025-10-10 15:34:26 +08:00
|
|
|
|
|
|
|
|
|
|
# 从 config.py 读取版本号(自动同步)
|
|
|
|
|
|
self.app_version = self._get_version_from_config()
|
|
|
|
|
|
|
2025-09-28 17:00:02 +08:00
|
|
|
|
self.app_publisher = "水滴智能科技"
|
|
|
|
|
|
self.app_url = "https://shuidrop.com/"
|
|
|
|
|
|
self.exe_name = "main.exe"
|
2025-10-10 15:34:26 +08:00
|
|
|
|
|
|
|
|
|
|
def _get_version_from_config(self):
|
|
|
|
|
|
"""从 config.py 读取版本号"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
config_file = self.project_root / "config.py"
|
|
|
|
|
|
if config_file.exists():
|
|
|
|
|
|
with open(config_file, 'r', encoding='utf-8') as f:
|
|
|
|
|
|
content = f.read()
|
|
|
|
|
|
import re
|
|
|
|
|
|
match = re.search(r'APP_VERSION\s*=\s*["\']([^"\']+)["\']', content)
|
|
|
|
|
|
if match:
|
|
|
|
|
|
version = match.group(1)
|
|
|
|
|
|
print(f"📦 从 config.py 读取版本号: v{version}")
|
|
|
|
|
|
return version
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"⚠️ 读取版本号失败: {e},使用默认版本")
|
|
|
|
|
|
|
|
|
|
|
|
return "1.0.0"
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
def check_prerequisites(self):
|
|
|
|
|
|
"""检查构建前提条件"""
|
|
|
|
|
|
print("🔍 检查构建前提条件...")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查NSIS安装
|
|
|
|
|
|
try:
|
|
|
|
|
|
result = subprocess.run(['makensis', '/VERSION'],
|
|
|
|
|
|
capture_output=True, text=True, check=True)
|
|
|
|
|
|
nsis_version = result.stdout.strip()
|
|
|
|
|
|
print(f"✅ NSIS 版本: {nsis_version}")
|
|
|
|
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
|
|
|
|
print("❌ 错误: 未找到NSIS或makensis命令")
|
|
|
|
|
|
print(" 请从 https://nsis.sourceforge.io/Download 下载并安装NSIS")
|
|
|
|
|
|
print(" 确保将NSIS添加到系统PATH环境变量")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
# 检查dist目录
|
|
|
|
|
|
if not self.dist_dir.exists():
|
|
|
|
|
|
print(f"❌ 错误: 未找到构建输出目录 {self.dist_dir}")
|
|
|
|
|
|
print(" 请先运行 build_production.py 构建应用程序")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
# 检查主程序文件
|
|
|
|
|
|
exe_path = self.dist_dir / self.exe_name
|
|
|
|
|
|
if not exe_path.exists():
|
|
|
|
|
|
print(f"❌ 错误: 未找到主程序文件 {exe_path}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✅ 找到主程序: {exe_path}")
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def prepare_assets(self):
|
|
|
|
|
|
"""准备安装包资源文件"""
|
|
|
|
|
|
print("📁 准备资源文件...")
|
|
|
|
|
|
|
|
|
|
|
|
# 创建assets目录
|
|
|
|
|
|
self.assets_dir.mkdir(exist_ok=True)
|
|
|
|
|
|
|
2025-09-29 16:08:16 +08:00
|
|
|
|
# 准备主程序图标
|
2025-09-28 17:00:02 +08:00
|
|
|
|
icon_sources = [
|
|
|
|
|
|
self.project_root / "static" / "ai_assistant_icon_64.png",
|
|
|
|
|
|
self.project_root / "static" / "ai_assistant_icon_32.png",
|
|
|
|
|
|
self.project_root / "static" / "ai_assistant_icon_16.png"
|
|
|
|
|
|
]
|
|
|
|
|
|
|
2025-09-29 16:08:16 +08:00
|
|
|
|
# 准备卸载程序专用图标
|
|
|
|
|
|
uninstall_icon_source = self.project_root / "static" / "ai_assistant_icon_uninstall.png"
|
|
|
|
|
|
|
|
|
|
|
|
# 转换主程序图标
|
2025-09-28 17:00:02 +08:00
|
|
|
|
icon_found = False
|
|
|
|
|
|
for icon_source in icon_sources:
|
|
|
|
|
|
if icon_source.exists():
|
|
|
|
|
|
try:
|
|
|
|
|
|
from PIL import Image
|
|
|
|
|
|
img = Image.open(icon_source)
|
|
|
|
|
|
ico_path = self.assets_dir / "icon.ico"
|
|
|
|
|
|
img.save(ico_path, format='ICO', sizes=[(16,16), (32,32), (48,48), (64,64)])
|
2025-09-29 16:08:16 +08:00
|
|
|
|
print(f"✅ 转换主程序图标: {icon_source.name} -> icon.ico")
|
2025-09-28 17:00:02 +08:00
|
|
|
|
icon_found = True
|
|
|
|
|
|
break
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
print("⚠️ 未安装PIL库,跳过图标转换")
|
|
|
|
|
|
break
|
|
|
|
|
|
except Exception as e:
|
2025-09-29 16:08:16 +08:00
|
|
|
|
print(f"⚠️ 主程序图标转换失败: {e}")
|
2025-09-28 17:00:02 +08:00
|
|
|
|
continue
|
|
|
|
|
|
|
2025-09-29 16:08:16 +08:00
|
|
|
|
# 转换卸载程序图标
|
|
|
|
|
|
uninstall_icon_found = False
|
|
|
|
|
|
if uninstall_icon_source.exists():
|
|
|
|
|
|
try:
|
|
|
|
|
|
from PIL import Image
|
|
|
|
|
|
img = Image.open(uninstall_icon_source)
|
|
|
|
|
|
uninstall_ico_path = self.assets_dir / "uninstall_icon.ico"
|
|
|
|
|
|
img.save(uninstall_ico_path, format='ICO', sizes=[(16,16), (32,32), (48,48), (64,64)])
|
|
|
|
|
|
print(f"✅ 转换卸载程序图标: {uninstall_icon_source.name} -> uninstall_icon.ico")
|
|
|
|
|
|
uninstall_icon_found = True
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
print("⚠️ 未安装PIL库,跳过卸载图标转换")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"⚠️ 卸载程序图标转换失败: {e}")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("⚠️ 未找到卸载程序专用图标,将使用主程序图标")
|
|
|
|
|
|
|
2025-09-28 17:00:02 +08:00
|
|
|
|
if not icon_found:
|
2025-09-29 16:08:16 +08:00
|
|
|
|
print("⚠️ 未找到主程序图标文件,将使用默认图标")
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
2025-09-29 16:08:16 +08:00
|
|
|
|
return {
|
|
|
|
|
|
'main_icon': icon_found,
|
|
|
|
|
|
'uninstall_icon': uninstall_icon_found
|
|
|
|
|
|
}
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
2025-09-29 16:08:16 +08:00
|
|
|
|
def generate_nsis_script(self, icon_info):
|
2025-09-28 17:00:02 +08:00
|
|
|
|
"""生成NSIS安装脚本"""
|
|
|
|
|
|
print("📝 生成NSIS安装脚本...")
|
|
|
|
|
|
|
2025-10-10 15:34:26 +08:00
|
|
|
|
# 标准化安装包命名(不带时间戳,便于固定下载地址)
|
|
|
|
|
|
installer_name = f"{self.app_name_en}_Setup_v{self.app_version}.exe"
|
|
|
|
|
|
# 示例: ShuiDi_AI_Assistant_Setup_v1.4.12.exe
|
|
|
|
|
|
|
|
|
|
|
|
print(f"📦 安装包名称: {installer_name}")
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
nsis_content = f'''# 水滴AI客服智能助手 NSIS 安装脚本
|
|
|
|
|
|
# 自动生成于 {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
|
|
|
|
|
|
|
|
|
|
|
Unicode True
|
|
|
|
|
|
|
|
|
|
|
|
# 定义应用程序信息
|
|
|
|
|
|
!define APP_NAME "{self.app_name}"
|
|
|
|
|
|
!define APP_NAME_EN "{self.app_name_en}"
|
|
|
|
|
|
!define APP_VERSION "{self.app_version}"
|
|
|
|
|
|
!define APP_PUBLISHER "{self.app_publisher}"
|
|
|
|
|
|
!define APP_URL "{self.app_url}"
|
|
|
|
|
|
!define APP_EXE "{self.exe_name}"
|
|
|
|
|
|
|
|
|
|
|
|
# 安装程序信息
|
|
|
|
|
|
Name "${{APP_NAME}} v${{APP_VERSION}}"
|
|
|
|
|
|
OutFile "output\\{installer_name}"
|
|
|
|
|
|
InstallDir "$PROGRAMFILES\\${{APP_NAME_EN}}"
|
|
|
|
|
|
InstallDirRegKey HKLM "Software\\${{APP_PUBLISHER}}\\${{APP_NAME_EN}}" "InstallPath"
|
|
|
|
|
|
|
|
|
|
|
|
# 界面设置
|
|
|
|
|
|
!include "MUI2.nsh"
|
|
|
|
|
|
!define MUI_ABORTWARNING
|
2025-09-29 16:08:16 +08:00
|
|
|
|
{f'!define MUI_ICON "assets\\\\icon.ico"' if icon_info.get('main_icon', False) else ''}
|
|
|
|
|
|
{f'!define MUI_UNICON "assets\\\\uninstall_icon.ico"' if icon_info.get('uninstall_icon', False) else f'!define MUI_UNICON "assets\\\\icon.ico"' if icon_info.get('main_icon', False) else ''}
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 页面配置
|
|
|
|
|
|
!insertmacro MUI_PAGE_WELCOME
|
|
|
|
|
|
!insertmacro MUI_PAGE_LICENSE "assets\\license.txt"
|
|
|
|
|
|
!insertmacro MUI_PAGE_DIRECTORY
|
|
|
|
|
|
!insertmacro MUI_PAGE_INSTFILES
|
|
|
|
|
|
!insertmacro MUI_PAGE_FINISH
|
|
|
|
|
|
|
|
|
|
|
|
!insertmacro MUI_UNPAGE_WELCOME
|
|
|
|
|
|
!insertmacro MUI_UNPAGE_CONFIRM
|
|
|
|
|
|
!insertmacro MUI_UNPAGE_INSTFILES
|
|
|
|
|
|
!insertmacro MUI_UNPAGE_FINISH
|
|
|
|
|
|
|
|
|
|
|
|
# 语言
|
|
|
|
|
|
!insertmacro MUI_LANGUAGE "SimpChinese"
|
|
|
|
|
|
|
|
|
|
|
|
# 版本信息
|
|
|
|
|
|
VIProductVersion "{self.app_version}.0"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "ProductName" "${{APP_NAME}}"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "Comments" "水滴AI客服智能助手"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "CompanyName" "${{APP_PUBLISHER}}"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "FileDescription" "${{APP_NAME}} 安装程序"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "FileVersion" "${{APP_VERSION}}"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "ProductVersion" "${{APP_VERSION}}"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "OriginalFilename" "{installer_name}"
|
|
|
|
|
|
VIAddVersionKey /LANG=2052 "LegalCopyright" "© 2024 ${{APP_PUBLISHER}}"
|
|
|
|
|
|
|
|
|
|
|
|
# 安装段
|
|
|
|
|
|
Section "MainSection" SEC01
|
|
|
|
|
|
SetOutPath "$INSTDIR"
|
|
|
|
|
|
SetOverwrite on
|
|
|
|
|
|
|
|
|
|
|
|
# 复制所有文件
|
|
|
|
|
|
File /r "..\\dist\\MultiPlatformGUI\\*.*"
|
|
|
|
|
|
|
2025-09-29 16:08:16 +08:00
|
|
|
|
# 复制图标文件到安装目录
|
|
|
|
|
|
{f'File "assets\\\\icon.ico"' if icon_info.get('main_icon', False) else ''}
|
|
|
|
|
|
{f'File "assets\\\\uninstall_icon.ico"' if icon_info.get('uninstall_icon', False) else ''}
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 创建开始菜单快捷方式
|
|
|
|
|
|
CreateDirectory "$SMPROGRAMS\\${{APP_NAME}}"
|
2025-09-29 16:08:16 +08:00
|
|
|
|
{f'CreateShortCut "$SMPROGRAMS\\\\${{APP_NAME}}\\\\${{APP_NAME}}.lnk" "$INSTDIR\\\\${{APP_EXE}}" "" "$INSTDIR\\\\icon.ico" 0' if icon_info.get('main_icon', False) else 'CreateShortCut "$SMPROGRAMS\\\\${{APP_NAME}}\\\\${{APP_NAME}}.lnk" "$INSTDIR\\\\${{APP_EXE}}"'}
|
|
|
|
|
|
{f'CreateShortCut "$SMPROGRAMS\\\\${{APP_NAME}}\\\\卸载${{APP_NAME}}.lnk" "$INSTDIR\\\\uninstall.exe" "" "$INSTDIR\\\\uninstall_icon.ico" 0' if icon_info.get('uninstall_icon', False) else f'CreateShortCut "$SMPROGRAMS\\\\${{APP_NAME}}\\\\卸载${{APP_NAME}}.lnk" "$INSTDIR\\\\uninstall.exe" "" "$INSTDIR\\\\icon.ico" 0' if icon_info.get('main_icon', False) else 'CreateShortCut "$SMPROGRAMS\\\\${{APP_NAME}}\\\\卸载${{APP_NAME}}.lnk" "$INSTDIR\\\\uninstall.exe"'}
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 创建桌面快捷方式
|
2025-09-29 16:08:16 +08:00
|
|
|
|
{f'CreateShortCut "$DESKTOP\\\\${{APP_NAME}}.lnk" "$INSTDIR\\\\${{APP_EXE}}" "" "$INSTDIR\\\\icon.ico" 0' if icon_info.get('main_icon', False) else 'CreateShortCut "$DESKTOP\\\\${{APP_NAME}}.lnk" "$INSTDIR\\\\${{APP_EXE}}"'}
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 写入注册表
|
|
|
|
|
|
WriteRegStr HKLM "Software\\${{APP_PUBLISHER}}\\${{APP_NAME_EN}}" "InstallPath" "$INSTDIR"
|
|
|
|
|
|
WriteRegStr HKLM "Software\\${{APP_PUBLISHER}}\\${{APP_NAME_EN}}" "Version" "${{APP_VERSION}}"
|
|
|
|
|
|
|
|
|
|
|
|
# 写入卸载信息
|
|
|
|
|
|
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "DisplayName" "${{APP_NAME}}"
|
|
|
|
|
|
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "UninstallString" "$INSTDIR\\uninstall.exe"
|
|
|
|
|
|
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "DisplayVersion" "${{APP_VERSION}}"
|
|
|
|
|
|
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "Publisher" "${{APP_PUBLISHER}}"
|
|
|
|
|
|
WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "URLInfoAbout" "${{APP_URL}}"
|
|
|
|
|
|
WriteRegDWORD HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "NoModify" 1
|
|
|
|
|
|
WriteRegDWORD HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}" "NoRepair" 1
|
|
|
|
|
|
|
|
|
|
|
|
# 创建卸载程序
|
|
|
|
|
|
WriteUninstaller "$INSTDIR\\uninstall.exe"
|
|
|
|
|
|
SectionEnd
|
|
|
|
|
|
|
|
|
|
|
|
# 卸载段
|
|
|
|
|
|
Section "Uninstall"
|
|
|
|
|
|
# 删除快捷方式
|
|
|
|
|
|
Delete "$SMPROGRAMS\\${{APP_NAME}}\\${{APP_NAME}}.lnk"
|
|
|
|
|
|
Delete "$SMPROGRAMS\\${{APP_NAME}}\\卸载${{APP_NAME}}.lnk"
|
|
|
|
|
|
RMDir "$SMPROGRAMS\\${{APP_NAME}}"
|
|
|
|
|
|
Delete "$DESKTOP\\${{APP_NAME}}.lnk"
|
|
|
|
|
|
|
|
|
|
|
|
# 删除安装目录
|
|
|
|
|
|
RMDir /r "$INSTDIR"
|
|
|
|
|
|
|
|
|
|
|
|
# 删除注册表项
|
|
|
|
|
|
DeleteRegKey HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${{APP_NAME_EN}}"
|
|
|
|
|
|
DeleteRegKey HKLM "Software\\${{APP_PUBLISHER}}\\${{APP_NAME_EN}}"
|
|
|
|
|
|
SectionEnd
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
# 写入NSIS脚本文件
|
|
|
|
|
|
# 使用UTF-8 BOM编码,NSIS可以正确识别
|
|
|
|
|
|
with open(self.nsis_script, 'w', encoding='utf-8-sig') as f:
|
|
|
|
|
|
f.write(nsis_content)
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✅ NSIS脚本已生成: {self.nsis_script}")
|
|
|
|
|
|
return installer_name
|
|
|
|
|
|
|
|
|
|
|
|
def create_license_file(self):
|
|
|
|
|
|
"""创建许可证文件"""
|
|
|
|
|
|
license_file = self.assets_dir / "license.txt"
|
|
|
|
|
|
license_content = f"""软件许可协议
|
|
|
|
|
|
|
|
|
|
|
|
{self.app_name} v{self.app_version}
|
|
|
|
|
|
|
|
|
|
|
|
版权所有 © 2025 {self.app_publisher}
|
|
|
|
|
|
|
|
|
|
|
|
使用本软件即表示您同意以下条款:
|
|
|
|
|
|
|
|
|
|
|
|
1. 本软件仅供合法用途使用
|
|
|
|
|
|
2. 不得对软件进行反向工程、反编译或反汇编
|
|
|
|
|
|
3. 软件按"原样"提供,不提供任何明示或暗示的保证
|
|
|
|
|
|
4. 在任何情况下,软件提供者均不对因使用本软件而产生的任何损害承担责任
|
|
|
|
|
|
|
|
|
|
|
|
如有疑问,请联系:{self.app_url}
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
with open(license_file, 'w', encoding='utf-8-sig') as f:
|
|
|
|
|
|
f.write(license_content)
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✅ 许可证文件已创建: {license_file}")
|
|
|
|
|
|
|
|
|
|
|
|
def build_installer(self):
|
|
|
|
|
|
"""构建安装包"""
|
|
|
|
|
|
print("🚀 开始构建NSIS安装包...")
|
|
|
|
|
|
|
|
|
|
|
|
# 创建输出目录
|
|
|
|
|
|
self.output_dir.mkdir(exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
# 执行NSIS编译
|
|
|
|
|
|
try:
|
|
|
|
|
|
cmd = ['makensis', str(self.nsis_script)]
|
|
|
|
|
|
result = subprocess.run(cmd, cwd=str(self.script_dir),
|
|
|
|
|
|
capture_output=True, text=True, check=True)
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ NSIS编译成功")
|
|
|
|
|
|
if result.stdout:
|
|
|
|
|
|
print("NSIS输出:")
|
|
|
|
|
|
print(result.stdout)
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
|
|
|
|
print("❌ NSIS编译失败")
|
|
|
|
|
|
print(f"错误信息: {e.stderr}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
|
"""执行完整的构建流程"""
|
|
|
|
|
|
print("=" * 60)
|
|
|
|
|
|
print(f"🔧 {self.app_name} 安装包构建工具")
|
|
|
|
|
|
print("=" * 60)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 1. 检查前提条件
|
|
|
|
|
|
if not self.check_prerequisites():
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 准备资源文件
|
2025-09-29 16:08:16 +08:00
|
|
|
|
icon_info = self.prepare_assets()
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 3. 创建许可证文件
|
|
|
|
|
|
self.create_license_file()
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 生成NSIS脚本
|
2025-09-29 16:08:16 +08:00
|
|
|
|
installer_name = self.generate_nsis_script(icon_info)
|
2025-09-28 17:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 5. 构建安装包
|
|
|
|
|
|
if not self.build_installer():
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
# 6. 显示结果
|
|
|
|
|
|
installer_path = self.output_dir / installer_name
|
|
|
|
|
|
if installer_path.exists():
|
|
|
|
|
|
installer_size = installer_path.stat().st_size / (1024 * 1024)
|
|
|
|
|
|
print("\n" + "=" * 60)
|
|
|
|
|
|
print("🎉 安装包构建成功!")
|
|
|
|
|
|
print(f"📁 安装包位置: {installer_path}")
|
|
|
|
|
|
print(f"📏 文件大小: {installer_size:.1f} MB")
|
|
|
|
|
|
print("🚀 可以直接分发给用户使用")
|
|
|
|
|
|
print("=" * 60)
|
|
|
|
|
|
return True
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("❌ 安装包文件未找到")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"❌ 构建过程出错: {e}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
|
"""主函数"""
|
|
|
|
|
|
installer = NSISInstaller()
|
|
|
|
|
|
success = installer.run()
|
|
|
|
|
|
|
|
|
|
|
|
if not success:
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
main()
|