203 lines
7.9 KiB
PowerShell
203 lines
7.9 KiB
PowerShell
# 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
|
||
}
|
||
|
||
# 同名库:当前用户 LocalAppData(F5 真数据源)、项目根、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"
|