From d19de412725b0980384c688347c6fe8ed199c31a Mon Sep 17 00:00:00 2001
From: luoqian <2769838458@qq.com>
Date: Thu, 21 May 2026 09:47:53 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=89=93=E5=8C=85?=
=?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=92=8C=E5=BA=94=E7=94=A8=E7=A8=8B=E5=BA=8F?=
=?UTF-8?q?=E5=9B=BE=E6=A0=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 package-scripts 目录,包含 Inno Setup 安装包打包脚本
- 在 Avalonia-PC.csproj 中配置应用程序图标
- 更新 .gitignore 忽略打包输出目录和工具目录
---
.gitignore | 2 +
Avalonia-PC/Avalonia-PC.csproj | 1 +
Avalonia-PC/Program.cs | 3 -
package-scripts/installer/Avalonia-PC.iss | 59 ++++++++
package-scripts/package-pc.bat | 32 ++++
package-scripts/package-pc.ps1 | 171 ++++++++++++++++++++++
6 files changed, 265 insertions(+), 3 deletions(-)
create mode 100644 package-scripts/installer/Avalonia-PC.iss
create mode 100644 package-scripts/package-pc.bat
create mode 100644 package-scripts/package-pc.ps1
diff --git a/.gitignore b/.gitignore
index 47ef72d..15db508 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,5 @@
/Avalonia-API/avalonia-api.db
/Avalonia-API/avalonia-api.db-shm
/Avalonia-API/avalonia-api.db-wal
+/package-output
+/package-scripts/tools
diff --git a/Avalonia-PC/Avalonia-PC.csproj b/Avalonia-PC/Avalonia-PC.csproj
index 46bde58..9be16cf 100644
--- a/Avalonia-PC/Avalonia-PC.csproj
+++ b/Avalonia-PC/Avalonia-PC.csproj
@@ -4,6 +4,7 @@
net10.0
enable
app.manifest
+ Assets\avalonia-logo.ico
true
diff --git a/Avalonia-PC/Program.cs b/Avalonia-PC/Program.cs
index 4735cba..2283dd5 100644
--- a/Avalonia-PC/Program.cs
+++ b/Avalonia-PC/Program.cs
@@ -91,9 +91,6 @@ namespace Avalonia_PC
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure()
.UsePlatformDetect()
-#if DEBUG
- .WithDeveloperTools()
-#endif
.WithInterFont()
.LogToTrace();
}
diff --git a/package-scripts/installer/Avalonia-PC.iss b/package-scripts/installer/Avalonia-PC.iss
new file mode 100644
index 0000000..4e51cde
--- /dev/null
+++ b/package-scripts/installer/Avalonia-PC.iss
@@ -0,0 +1,59 @@
+#ifndef AppName
+#define AppName "Avalonia-PC"
+#endif
+#ifndef AppVersion
+#define AppVersion "1.0.0"
+#endif
+#ifndef AppPublisher
+#define AppPublisher "QiCheng"
+#endif
+#ifndef AppExeName
+#define AppExeName "Avalonia-PC.exe"
+#endif
+#ifndef SourceDir
+#define SourceDir "..\..\package-output\publish\Avalonia-PC\win-x64"
+#endif
+#ifndef OutputDir
+#define OutputDir "..\..\package-output\installer"
+#endif
+#ifndef RepoRoot
+#define RepoRoot "..\.."
+#endif
+#ifndef ChineseLanguageFile
+#define ChineseLanguageFile "compiler:Default.isl"
+#endif
+
+[Setup]
+AppId={{7E41DD4C-FBF3-4C65-8D9F-4F2D794BC284}
+AppName={#AppName}
+AppVersion={#AppVersion}
+AppPublisher={#AppPublisher}
+DefaultDirName={autopf}\{#AppName}
+DefaultGroupName={#AppName}
+OutputDir={#OutputDir}
+OutputBaseFilename={#AppName}-Setup-{#AppVersion}-win-x64
+SetupIconFile={#RepoRoot}\Avalonia-PC\Assets\avalonia-logo.ico
+Compression=lzma2
+SolidCompression=yes
+WizardStyle=modern
+PrivilegesRequired=admin
+ArchitecturesAllowed=x64compatible
+ArchitecturesInstallIn64BitMode=x64compatible
+DisableProgramGroupPage=yes
+UninstallDisplayIcon={app}\{#AppExeName}
+
+[Languages]
+Name: "chinesesimp"; MessagesFile: "{#ChineseLanguageFile}"
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+Source: "{#SourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+
+[Icons]
+Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"
+Name: "{autodesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desktopicon
+
+[Run]
+Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
diff --git a/package-scripts/package-pc.bat b/package-scripts/package-pc.bat
new file mode 100644
index 0000000..10ff627
--- /dev/null
+++ b/package-scripts/package-pc.bat
@@ -0,0 +1,32 @@
+@echo off
+setlocal
+
+cd /d "%~dp0.."
+
+set "APP_VERSION=1.0.0"
+set "APP_NAME=Avalonia-PC"
+set "APP_PUBLISHER=QiCheng"
+
+echo Packaging %APP_NAME% %APP_VERSION% for Windows PC...
+echo.
+
+powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0package-pc.ps1" -Version "%APP_VERSION%" -AppName "%APP_NAME%" -Publisher "%APP_PUBLISHER%" -SingleFile -InstallInnoSetupIfMissing
+
+set "EXIT_CODE=%ERRORLEVEL%"
+echo.
+
+if "%EXIT_CODE%"=="0" (
+ echo Done.
+ echo Installer output: %CD%\package-output\installer
+) else if "%EXIT_CODE%"=="2" (
+ echo Publish completed, but installer was not created because Inno Setup 6 is not installed.
+ echo This BAT can download Inno Setup into package-scripts\tools. Run it again and allow network access.
+ echo.
+ echo Publish output: %CD%\package-output\publish\Avalonia-PC
+) else (
+ echo Packaging failed. Exit code: %EXIT_CODE%
+)
+
+echo.
+pause
+exit /b %EXIT_CODE%
diff --git a/package-scripts/package-pc.ps1 b/package-scripts/package-pc.ps1
new file mode 100644
index 0000000..67ba6bf
--- /dev/null
+++ b/package-scripts/package-pc.ps1
@@ -0,0 +1,171 @@
+[CmdletBinding()]
+param(
+ [string]$Configuration = "Release",
+ [string]$Runtime = "win-x64",
+ [string]$Version = "1.0.0",
+ [string]$AppName = "Avalonia-PC",
+ [string]$Publisher = "QiCheng",
+ [bool]$SelfContained = $true,
+ [switch]$SingleFile,
+ [switch]$InstallInnoSetupIfMissing,
+ [switch]$SkipInstaller
+)
+
+$ErrorActionPreference = "Stop"
+
+$repoRoot = Split-Path -Parent $PSScriptRoot
+$projectPath = Join-Path $repoRoot "Avalonia-PC\Avalonia-PC.csproj"
+$installerScript = Join-Path $PSScriptRoot "installer\Avalonia-PC.iss"
+$buildStamp = Get-Date -Format "yyyyMMddHHmmss"
+$publishDir = Join-Path $repoRoot "package-output\publish\Avalonia-PC\$Runtime-$buildStamp"
+$installerDir = Join-Path $repoRoot "package-output\installer"
+$appExeName = "Avalonia-PC.exe"
+$toolsDir = Join-Path $PSScriptRoot "tools"
+$innoSetupDir = Join-Path $toolsDir "InnoSetup6"
+$innoSetupInstaller = Join-Path $toolsDir "downloads\innosetup-6.7.2.exe"
+$innoSetupDownloadUrl = "https://github.com/jrsoftware/issrc/releases/download/is-6_7_2/innosetup-6.7.2.exe"
+$chineseSimplifiedLanguageFile = Join-Path $innoSetupDir "Languages\ChineseSimplified.isl"
+$chineseSimplifiedLanguageUrl = "https://raw.githubusercontent.com/kira-96/Inno-Setup-Chinese-Simplified-Translation/main/ChineseSimplified.isl"
+
+function Find-InnoSetupCompiler {
+ $localCompiler = Join-Path $innoSetupDir "ISCC.exe"
+ if (Test-Path $localCompiler) {
+ return $localCompiler
+ }
+
+ $command = Get-Command "iscc" -ErrorAction SilentlyContinue
+ if ($command) {
+ return $command.Source
+ }
+
+ $candidates = @(
+ "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
+ "$env:ProgramFiles\Inno Setup 6\ISCC.exe",
+ "$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe"
+ )
+
+ foreach ($candidate in $candidates) {
+ if ($candidate -and (Test-Path $candidate)) {
+ return $candidate
+ }
+ }
+
+ return $null
+}
+
+function Install-LocalInnoSetup {
+ New-Item -ItemType Directory -Force -Path (Split-Path -Parent $innoSetupInstaller), $innoSetupDir | Out-Null
+
+ if (-not (Test-Path $innoSetupInstaller)) {
+ Write-Host "Downloading Inno Setup 6 to: $innoSetupInstaller"
+ Invoke-WebRequest -Uri $innoSetupDownloadUrl -OutFile $innoSetupInstaller
+ }
+
+ Write-Host "Installing local Inno Setup 6 to: $innoSetupDir"
+ & $innoSetupInstaller /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /CURRENTUSER /DIR="$innoSetupDir"
+ if ($LASTEXITCODE -ne 0) {
+ throw "Inno Setup local install failed with exit code $LASTEXITCODE"
+ }
+}
+
+function Ensure-ChineseSimplifiedLanguageFile {
+ if (Test-Path $chineseSimplifiedLanguageFile) {
+ return
+ }
+
+ $languageDir = Split-Path -Parent $chineseSimplifiedLanguageFile
+ New-Item -ItemType Directory -Force -Path $languageDir | Out-Null
+
+ Write-Host "Downloading Inno Setup Chinese language file to: $chineseSimplifiedLanguageFile"
+ Invoke-WebRequest -Uri $chineseSimplifiedLanguageUrl -OutFile $chineseSimplifiedLanguageFile
+}
+
+if (-not (Test-Path $projectPath)) {
+ throw "Project file not found: $projectPath"
+}
+
+if (-not (Test-Path $installerScript)) {
+ throw "Installer script not found: $installerScript"
+}
+
+New-Item -ItemType Directory -Force -Path $publishDir, $installerDir | Out-Null
+
+Write-Host "Publishing $AppName ($Configuration, $Runtime)..."
+
+$publishArgs = @(
+ "publish",
+ $projectPath,
+ "-c", $Configuration,
+ "-r", $Runtime,
+ "--self-contained", $SelfContained.ToString().ToLowerInvariant(),
+ "-o", $publishDir,
+ "/p:Version=$Version",
+ "/p:PublishSingleFile=$($SingleFile.IsPresent.ToString().ToLowerInvariant())",
+ "/p:IncludeNativeLibrariesForSelfExtract=true",
+ "/p:PublishTrimmed=false",
+ "/p:DebugType=None",
+ "/p:DebugSymbols=false"
+)
+
+dotnet @publishArgs
+if ($LASTEXITCODE -ne 0) {
+ throw "dotnet publish failed with exit code $LASTEXITCODE"
+}
+
+Get-ChildItem -Path $publishDir -Filter "*.pdb" -Recurse -File | Remove-Item -Force
+
+$publishedExe = Join-Path $publishDir $appExeName
+if (-not (Test-Path $publishedExe)) {
+ throw "Publish completed, but executable was not found: $publishedExe"
+}
+
+Write-Host "Publish output: $publishDir"
+
+$localInnoCompiler = Join-Path $innoSetupDir "ISCC.exe"
+
+if ($SkipInstaller) {
+ Write-Host "SkipInstaller was specified. Installer package was not created."
+ exit 0
+}
+
+if ($InstallInnoSetupIfMissing -and -not (Test-Path $localInnoCompiler)) {
+ Install-LocalInnoSetup
+}
+
+$iscc = Find-InnoSetupCompiler
+if (-not $iscc) {
+ if ($InstallInnoSetupIfMissing) {
+ Install-LocalInnoSetup
+ $iscc = Find-InnoSetupCompiler
+ }
+
+ if (-not $iscc) {
+ Write-Warning "Inno Setup compiler (ISCC.exe) was not found. Rerun package-scripts\package-pc.bat and let it download Inno Setup into package-scripts\tools."
+ Write-Host "The publish output is ready at: $publishDir"
+ exit 2
+ }
+}
+
+Write-Host "Building installer with Inno Setup..."
+Write-Host "Using Inno Setup compiler: $iscc"
+Ensure-ChineseSimplifiedLanguageFile
+
+$isccArgs = @(
+ "/DAppName=$AppName",
+ "/DAppVersion=$Version",
+ "/DAppPublisher=$Publisher",
+ "/DAppExeName=$appExeName",
+ "/DSourceDir=$publishDir",
+ "/DOutputDir=$installerDir",
+ "/DRepoRoot=$repoRoot",
+ "/DChineseLanguageFile=$chineseSimplifiedLanguageFile",
+ $installerScript
+)
+
+& $iscc @isccArgs
+if ($LASTEXITCODE -ne 0) {
+ throw "Inno Setup failed with exit code $LASTEXITCODE"
+}
+
+$setupFile = Join-Path $installerDir "$AppName-Setup-$Version-$Runtime.exe"
+Write-Host "Installer created: $setupFile"