<# .SYNOPSIS 发布 SSPCTester WPF 主程序。 .DESCRIPTION 用 dotnet publish 生成 Release 版本(默认 win-x64、单文件、自包含), 完成后在资源管理器中打开输出目录。 .PARAMETER Runtime 目标运行时标识符(RID)。默认 win-x64。 .PARAMETER SelfContained 是否自包含 .NET 运行时。默认 $true,目标机无需安装 .NET。 .PARAMETER SingleFile 是否生成单文件 exe。默认 $false(多文件部署)。 注意:.NET 9 SDK 编译 net8.0-windows + SingleFile 在 WPF 资源加载时存在兼容问题, 会出现进程驻留但无窗口的现象,故默认关闭。 .PARAMETER Output 输出目录,默认 .\publish\。 .PARAMETER Clean 发布前删除现有 publish 目录。 .PARAMETER NoOpen 完成后不自动打开资源管理器。 .EXAMPLE .\publish.ps1 .EXAMPLE .\publish.ps1 -Runtime win-x64 -SelfContained:$false #> [CmdletBinding()] param( [string]$Runtime = 'win-x64', [bool]$SelfContained = $true, [bool]$SingleFile = $false, [string]$Output, [switch]$Clean, [switch]$NoOpen ) $ErrorActionPreference = 'Stop' function Initialize-ConsoleUtf8 { try { if ($IsWindows) { & chcp.com 65001 > $null } } catch { Write-Warning "无法切换到 UTF-8 代码页,将继续使用当前代码页。" } $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [Console]::InputEncoding = $utf8NoBom [Console]::OutputEncoding = $utf8NoBom Set-Variable -Name OutputEncoding -Value $utf8NoBom -Scope Global if ([string]::IsNullOrWhiteSpace($env:DOTNET_CLI_UI_LANGUAGE)) { $env:DOTNET_CLI_UI_LANGUAGE = 'zh-Hans' } } Initialize-ConsoleUtf8 $root = $PSScriptRoot Set-Location $root $uiProj = Join-Path $root 'SSPCTester.UI\SSPCTester.UI.csproj' if (-not (Test-Path $uiProj)) { throw "Project not found: $uiProj" } if ([string]::IsNullOrWhiteSpace($Output)) { $Output = Join-Path $root "publish\$Runtime" } function Write-Step([string]$msg) { Write-Host "" Write-Host "==> $msg" -ForegroundColor Cyan } if ($Clean -and (Test-Path $Output)) { Write-Step "Clean $Output" Remove-Item -Path $Output -Recurse -Force } Write-Step "Publish (Release, $Runtime, SelfContained=$SelfContained, SingleFile=$SingleFile)" $nativeDll = Join-Path $root 'Docs\PCIe8586驱动接入资料\native\ACTS1000_64.dll' if (-not (Test-Path -LiteralPath $nativeDll)) { Write-Warning "未找到 ACTS1000_64.dll。Mock 模式可运行,真卡模式需从厂商 SDK 取得 x64 DLL 并放入 Docs\PCIe8586驱动接入资料\native。" } # VS、Code Runner 或上一次异常中断的构建可能留下编译服务器, # 持有 WPF obj 下的 App.g.cs / MarkupCompile.cache,导致打包报 Access denied。 Write-Step "Release stale .NET build locks" & dotnet build-server shutdown if ($LASTEXITCODE -ne 0) { Write-Warning "无法关闭 .NET build server,将继续尝试发布。" } $publishArgs = @( 'publish', $uiProj, '-c', 'Release', '-r', $Runtime, '-m:1', "-p:SelfContained=$($SelfContained.ToString().ToLower())", "-p:PublishSingleFile=$($SingleFile.ToString().ToLower())", '-p:UseSharedCompilation=false', '-p:IncludeNativeLibrariesForSelfExtract=true', '-p:DebugType=embedded', '-o', $Output, '--nologo' ) & dotnet @publishArgs if ($LASTEXITCODE -ne 0) { throw "Publish failed (exit $LASTEXITCODE)." } $exe = Join-Path $Output 'SSPCTester.UI.exe' if (Test-Path $exe) { $size = [Math]::Round((Get-Item $exe).Length / 1MB, 2) Write-Host "" Write-Host "==> Done" -ForegroundColor Green Write-Host " Output : $Output" Write-Host " Exe : SSPCTester.UI.exe ($size MB)" } else { Write-Warning "未在输出目录找到 SSPCTester.UI.exe,请检查 publish 日志。" } if (-not $NoOpen) { if (Test-Path $Output) { if (Test-Path $exe) { $selectArg = '/select,"' + $exe + '"' Start-Process explorer.exe -ArgumentList $selectArg } else { $openArg = '"' + $Output + '"' Start-Process explorer.exe -ArgumentList $openArg } } }