[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"