hi-client/package_windows_single_exe.ps1
shanshanzhong 7956349c0a feat(打包): 添加Windows单文件打包脚本和工具安装脚本
添加install_build_tools.bat用于自动安装构建工具
添加package_windows_single_exe.ps1用于打包Flutter应用为单文件
改进inno_setup.sas增加卸载清理逻辑和进程终止功能
2025-11-24 00:52:28 -08:00

168 lines
5.5 KiB
PowerShell

#Requires -RunAsAdministrator
<#
.SYNOPSIS
Builds and packages a Flutter Windows application into a single executable.
.DESCRIPTION
This script automates the entire process of creating a single-file executable for a Flutter Windows project.
It performs the following steps:
1. Checks for and installs Chocolatey if not present.
2. Installs Enigma Virtual Box and 7-Zip using Chocolatey.
3. Builds the Flutter application in release mode.
4. Packages the build output into a single EXE using Enigma Virtual Box.
5. If Enigma fails, it falls back to creating a 7-Zip self-extracting archive.
6. Places the final packaged executable in the 'dist' directory.
.NOTES
- This script must be run with Administrator privileges to install software.
- An internet connection is required for the first run to download and install dependencies.
#>
# --- Configuration ---
$ErrorActionPreference = "Stop"
$buildPath = ".\build\windows\x64\runner\Release"
$outputPath = ".\dist"
# --- Helper Functions ---
function Test-CommandExists {
param($command)
return (Get-Command $command -ErrorAction SilentlyContinue)
}
function Install-Chocolatey {
if (Test-CommandExists "choco") {
Write-Host "✅ Chocolatey is already installed."
return
}
Write-Host "Chocolatey not found. Installing..."
try {
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
Write-Host "✅ Chocolatey installed successfully."
} catch {
Write-Host "❌ Failed to install Chocolatey. Please install it manually and re-run the script."
exit 1
}
}
function Install-Tools {
Write-Host "Checking for required tools (Enigma Virtual Box, 7-Zip)..."
$tools = @("enigma-virtual-box", "7zip")
foreach ($tool in $tools) {
if (choco list --local-only --exact $tool) {
Write-Host "$tool is already installed."
} else {
Write-Host "Installing $tool..."
try {
choco install $tool -y --force
Write-Host "$tool installed successfully."
} catch {
Write-Host "❌ Failed to install $tool."
exit 1
}
}
}
}
# --- Main Script ---
# 1. Setup Environment
Write-Host "=== 1/4: Setting up build environment ==="
Install-Chocolatey
Install-Tools
# 2. Build Flutter App
Write-Host "=== 2/4: Building Flutter Windows application (Release) ==="
try {
flutter build windows --release
} catch {
Write-Host "❌ Flutter build failed."
exit 1
}
# 3. Package Application
Write-Host "=== 3/4: Packaging into a single executable ==="
if (-not (Test-Path $buildPath)) {
Write-Host "❌ Build directory not found: $buildPath"
exit 1
}
# Create output directory
New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
# Get main executable
$exeFile = Get-ChildItem -Path $buildPath -Filter "*.exe" | Select-Object -First 1
if (-not $exeFile) {
Write-Host "❌ No executable found in build directory."
exit 1
}
$inputExe = $exeFile.FullName
$outputExe = "$outputPath\$($exeFile.BaseName)_Single.exe"
$enigmaCliPath = "C:\Program Files\Enigma Virtual Box\enigmavb.exe"
$packageSuccess = $false
# Attempt to package with Enigma Virtual Box
if (Test-Path $enigmaCliPath) {
Write-Host "Attempting to package with Enigma Virtual Box..."
try {
& $enigmaCliPath /quiet /project "$outputPath\project.evb" /input "$inputExe" /output "$outputExe" /folder "$buildPath" /compress 3 /deleteext
if ($?) {
Write-Host "✅ Enigma Virtual Box packaging successful."
$packageSuccess = $true
} else {
Write-Host "⚠️ Enigma Virtual Box packaging failed. Exit code: $lastexitcode"
}
} catch {
Write-Host "⚠️ An error occurred during Enigma Virtual Box packaging."
}
} else {
Write-Host "⚠️ Enigma Virtual Box not found at $enigmaCliPath."
}
# 4. Fallback to 7-Zip if Enigma failed
if (-not $packageSuccess) {
Write-Host "=== 4/4: Fallback: Packaging with 7-Zip SFX ==="
$7zipCliPath = "C:\Program Files\7-Zip\7z.exe"
$outputSfx = "$outputPath\$($exeFile.BaseName)_Package.exe"
if (-not (Test-Path $7zipCliPath)) {
Write-Host "❌ 7-Zip not found. Cannot create self-extracting archive."
exit 1
}
$sfxConfig = @'
;!@Install@!UTF-8!
Title="Flutter Application"
BeginPrompt="Do you want to extract and run the application?"
RunProgram="%%T\%%S\$($exeFile.Name)"
;!@InstallEnd@!
'@
$sfxConfigFile = "$outputPath\sfx_config.txt"
Set-Content -Path $sfxConfigFile -Value $sfxConfig
try {
& $7zipCliPath a -sfx7z.sfx "$outputSfx" "$buildPath\*" -r "-i!$sfxConfigFile"
Write-Host "✅ 7-Zip self-extracting archive created successfully."
$outputExe = $outputSfx
$packageSuccess = $true
} catch {
Write-Host "❌ 7-Zip packaging failed."
exit 1
}
}
# --- Final Summary ---
if ($packageSuccess) {
$finalSize = (Get-Item $outputExe).Length / 1MB
Write-Host "================================================"
Write-Host "✅ Packaging Complete!"
Write-Host " Output file: $outputExe"
Write-Host " Size: $([math]::Round($finalSize, 2)) MB"
Write-Host "================================================"
} else {
Write-Host "❌ All packaging attempts failed."
}