Files
qhmes/yy-admin-master/installer/build-installer.ps1
2026-05-18 17:31:18 +08:00

203 lines
7.9 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Release publish + WebView2 bootstrap download + Inno Setup ISCC
# Requires Inno Setup 6 (ISCC.exe)
#
# 注意:与 YY.Admin\publish.cmd 输出目录不同;本脚本使用 bin\Release\...\win-x64\publish。
# 本地 F5 / 双击 bin 下 exe 时SQLite 实际写在 %LocalAppData%\YY.Admin\Data\(不是工程或 bin 目录)。
# 同步步骤会优先把该目录下的库打进 publish与其它机上「和你本机一致」的安装模板对齐。
param(
[switch]$NoLocalSync
)
$ErrorActionPreference = 'Stop'
$Root = Split-Path -Parent $PSScriptRoot
$Csproj = Join-Path $Root 'YY.Admin\YY.Admin.csproj'
$Tfm = 'net8.0-windows10.0.19041'
$Rid = 'win-x64'
$BinReleaseWin64 = Join-Path $Root "YY.Admin\bin\Release\$Tfm\$Rid"
$BinDebugWin64 = Join-Path $Root "YY.Admin\bin\Debug\$Tfm\$Rid"
$PublishRel = "YY.Admin\bin\Release\$Tfm\$Rid\publish"
$PublishDir = Join-Path $Root $PublishRel
$ProjAdmin = Join-Path $Root 'YY.Admin'
# 与 SqlSugar 解析一致:相对路径 SQLite 落在当前 Windows 用户的 LocalAppData
$DevUserDataDir = if ($env:LOCALAPPDATA) { Join-Path $env:LOCALAPPDATA 'YY.Admin\Data' } else { '' }
$DevUserAppSettingsDir = if ($env:LOCALAPPDATA) { Join-Path $env:LOCALAPPDATA 'YY.Admin\AppSettings' } else { '' }
$RedistDir = Join-Path $PSScriptRoot 'redist'
$WebView2Exe = Join-Path $RedistDir 'MicrosoftEdgeWebview2Setup.exe'
$WebView2Url = 'https://go.microsoft.com/fwlink/p/?LinkId=2124703'
$SnapshotDir = Join-Path ([System.IO.Path]::GetTempPath()) ("yyadmin-publish-snap-{0}" -f [Guid]::NewGuid().ToString('n'))
Write-Host '>>> dotnet publish (Release, win-x64)...'
# publish 会清空输出目录:若你平时只在 publish 里测,先把其中的库暂存,供同步步骤一并参与“最新”比较
$hadPublishRoot = Test-Path -LiteralPath $PublishDir
if ($hadPublishRoot -and -not $NoLocalSync) {
$snapDb = @()
foreach ($dbName in @('Admin.NET.db', 'Slave.db')) {
$pp = Join-Path $PublishDir $dbName
if (Test-Path -LiteralPath $pp) { $snapDb += , $pp }
}
$pubApps = Join-Path $PublishDir 'AppSettings'
$hasPubApps = Test-Path -LiteralPath $pubApps
if ($snapDb.Count -gt 0 -or $hasPubApps) {
New-Item -ItemType Directory -Force -Path $SnapshotDir | Out-Null
foreach ($p in $snapDb) {
Copy-Item -LiteralPath $p -Destination (Join-Path $SnapshotDir (Split-Path $p -Leaf)) -Force
}
if ($hasPubApps) {
Copy-Item -LiteralPath $pubApps -Destination (Join-Path $SnapshotDir 'AppSettings') -Recurse -Force
}
}
}
dotnet publish $Csproj -c Release `
-p:IncludeNativeLibrariesForSelfExtract=true `
-p:EnableCompressionInSingleFile=true `
--verbosity minimal
if (-not (Test-Path $PublishDir)) {
throw "Publish output not found: $PublishDir"
}
$cfgPublish = Join-Path $PublishDir 'Configuration\appsettings.json'
if (-not (Test-Path $cfgPublish)) {
throw "Missing Configuration\appsettings.json under publish (ExcludeFromSingleFile required). Path: $cfgPublish"
}
if (-not $NoLocalSync) {
Write-Host '>>> Sync local runtime data into publish (databases + AppSettings, match local test)...'
function Get-BestExistingPath {
param([string[]]$Paths)
$bestItem = $null
foreach ($p in $Paths) {
if (-not $p -or -not (Test-Path -LiteralPath $p)) { continue }
$fi = Get-Item -LiteralPath $p
if (-not $bestItem) { $bestItem = $fi; continue }
if ($fi.LastWriteTime -gt $bestItem.LastWriteTime) { $bestItem = $fi; continue }
# 修改时间相同(例如复制残留)时优先体积更大的一份,一般数据更全
if ($fi.LastWriteTime -eq $bestItem.LastWriteTime -and $fi.Length -gt $bestItem.Length) { $bestItem = $fi }
}
if ($bestItem) { return $bestItem.FullName }
return $null
}
# 同名库:当前用户 LocalAppDataF5 真数据源、项目根、publish.cmd、bin、publish、快照…
foreach ($dbName in @('Admin.NET.db', 'Slave.db')) {
$paths = @()
if ($DevUserDataDir -and (Test-Path -LiteralPath $DevUserDataDir)) {
$paths += (Join-Path $DevUserDataDir $dbName)
}
$paths += @(
(Join-Path $ProjAdmin $dbName),
(Join-Path $ProjAdmin "publish\$dbName"),
(Join-Path $BinReleaseWin64 $dbName),
(Join-Path $BinDebugWin64 $dbName),
(Join-Path $BinReleaseWin64 "publish\$dbName"),
(Join-Path $BinDebugWin64 "publish\$dbName"),
(Join-Path $PublishDir $dbName)
)
if (Test-Path -LiteralPath $SnapshotDir) {
$sp = Join-Path $SnapshotDir $dbName
if (Test-Path -LiteralPath $sp) { $paths += $sp }
}
$src = Get-BestExistingPath -Paths $paths
if ($src) {
$dst = Join-Path $PublishDir $dbName
Copy-Item -LiteralPath $src -Destination $dst -Force
$dstItem = Get-Item -LiteralPath $dst
$t = $dstItem.LastWriteTime.ToString('yyyy-MM-dd HH:mm')
$len = $dstItem.Length
Write-Host " $dbName <= $src (publish 时间: $t, 大小: $len 字节)"
} else {
Write-Host " (skip) $dbName — 未在任意候选路径找到(含当前 publish 文件夹)"
}
}
# AppSettings\:先 Release、再 Debug再上一版 publish 下的 AppSettings后者覆盖适配只在 publish 目录测试)
foreach ($bin in @($BinReleaseWin64, $BinDebugWin64)) {
$appSettingsSrc = Join-Path $bin 'AppSettings'
if (Test-Path -LiteralPath $appSettingsSrc) {
$appSettingsDst = Join-Path $PublishDir 'AppSettings'
Copy-Item -LiteralPath $appSettingsSrc -Destination $appSettingsDst -Recurse -Force
Write-Host " AppSettings\ <= $appSettingsSrc"
}
}
$snapApps = Join-Path $SnapshotDir 'AppSettings'
if (Test-Path -LiteralPath $snapApps) {
$appSettingsDst = Join-Path $PublishDir 'AppSettings'
Copy-Item -LiteralPath $snapApps -Destination $appSettingsDst -Recurse -Force
Write-Host " AppSettings\ <= $snapApps (previous publish)"
}
# 最后覆盖为当前登录 Windows 用户在 LocalAppData 下的设置(与 F5 调试一致)
if ($DevUserAppSettingsDir -and (Test-Path -LiteralPath $DevUserAppSettingsDir)) {
$appSettingsDst = Join-Path $PublishDir 'AppSettings'
Copy-Item -LiteralPath $DevUserAppSettingsDir -Destination $appSettingsDst -Recurse -Force
Write-Host " AppSettings\ <= $DevUserAppSettingsDir (LocalAppData)"
}
} else {
Write-Host '>>> Skip local sync (-NoLocalSync).'
}
New-Item -ItemType Directory -Force -Path $RedistDir | Out-Null
if (-not (Test-Path $WebView2Exe)) {
Write-Host '>>> Downloading WebView2 Evergreen bootstrapper...'
Invoke-WebRequest -Uri $WebView2Url -OutFile $WebView2Exe -UseBasicParsing
}
function Find-InnoCompiler {
if ($env:ISCC -and (Test-Path -LiteralPath $env:ISCC)) {
return $env:ISCC
}
if ($env:INNO_SETUP_DIR) {
$p = Join-Path $env:INNO_SETUP_DIR.TrimEnd('\') 'ISCC.exe'
if (Test-Path -LiteralPath $p) {
return $p
}
}
$cmd = Get-Command 'iscc.exe' -ErrorAction SilentlyContinue
if ($cmd -and $cmd.Source -and (Test-Path -LiteralPath $cmd.Source)) {
return $cmd.Source
}
$candidates = @(
'D:\Inno Setup 6\ISCC.exe'
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
"${env:ProgramFiles}\Inno Setup 6\ISCC.exe"
"${env:LocalAppData}\Programs\Inno Setup 6\ISCC.exe"
)
foreach ($c in $candidates) {
if ($c -and (Test-Path -LiteralPath $c)) {
return $c
}
}
return $null
}
$iscc = Find-InnoCompiler
if (-not $iscc) {
throw @'
ISCC.exe not found.
1) Install Inno Setup 6: https://jrsoftware.org/isdl.php
2) Or set env ISCC to full path of ISCC.exe, e.g.:
set ISCC=C:\Program Files (x86)\Inno Setup 6\ISCC.exe
3) Or set INNO_SETUP_DIR to the Inno Setup 6 folder.
Then run this script again.
'@
}
Write-Host ">>> Using ISCC: $iscc"
$iss = Join-Path $PSScriptRoot 'YY.Admin.Setup.iss'
Write-Host '>>> Compiling installer (working dir: installer)...'
Push-Location $PSScriptRoot
try {
& $iscc "`"$iss`""
} finally {
Pop-Location
}
$outDir = Join-Path $Root '_installer_output'
Write-Host ">>> Done. Output folder: $outDir"