Files
qhmes/yy-admin-master/installer/build-installer.ps1

203 lines
7.9 KiB
PowerShell
Raw Normal View History

# Release publish + WebView2 bootstrap download + Inno Setup ISCC
# Requires Inno Setup 6 (ISCC.exe)
2026-05-18 17:31:18 +08:00
#
# 注意:与 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'
2026-05-18 17:31:18 +08:00
$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
2026-05-18 17:31:18 +08:00
$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'
2026-05-18 17:31:18 +08:00
$SnapshotDir = Join-Path ([System.IO.Path]::GetTempPath()) ("yyadmin-publish-snap-{0}" -f [Guid]::NewGuid().ToString('n'))
Write-Host '>>> dotnet publish (Release, win-x64)...'
2026-05-18 17:31:18 +08:00
# 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"
}
2026-05-18 17:31:18 +08:00
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"