netx/packaging/sign_release.ps1
oliver 41ab4921a0 Fix Windows PowerShell parsing on Server 2012: UTF-8 BOM scripts.
Chinese packaging scripts without BOM were misread as ANSI and failed at first-run.
Document that bundled Python 3.13+ needs Server 2016+ / Win10+.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-07 10:53:29 +08:00

78 lines
2.6 KiB
PowerShell

param(
[Parameter(Mandatory = $true)]
[string[]]$Files,
[string]$Thumbprint = "",
[string]$PfxPath = "",
[string]$PfxPassword = "",
[string]$TimestampUrl = "http://timestamp.digicert.com",
[string]$Description = "NetX"
)
# Sign release artifacts with signtool (Authenticode).
# Requires Windows SDK / signtool.exe and a code-signing certificate.
#
# Examples:
# .\sign_release.ps1 -Files .\packaging\release\NetX-Setup-0.4.0.exe -Thumbprint ABCDEF...
# .\sign_release.ps1 -Files .\packaging\release\*.exe -PfxPath .\certs\netx.pfx -PfxPassword ***
$ErrorActionPreference = "Stop"
function Find-SignTool {
$cmd = Get-Command signtool.exe -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Source }
$roots = @(
"${env:ProgramFiles(x86)}\Windows Kits\10\bin",
"${env:ProgramFiles}\Windows Kits\10\bin"
)
foreach ($root in $roots) {
if (-not (Test-Path $root)) { continue }
$hit = Get-ChildItem -Path $root -Recurse -Filter signtool.exe -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match '\\x64\\signtool\.exe$' } |
Select-Object -First 1
if ($hit) { return $hit.FullName }
}
return $null
}
$signtool = Find-SignTool
if (-not $signtool) {
throw "signtool_not_found: install Windows SDK or add signtool.exe to PATH"
}
if (-not $Thumbprint -and -not $PfxPath) {
if ($env:NETX_SIGN_THUMBPRINT) { $Thumbprint = $env:NETX_SIGN_THUMBPRINT }
if ($env:NETX_SIGN_PFX) { $PfxPath = $env:NETX_SIGN_PFX }
if ($env:NETX_SIGN_PFX_PASSWORD) { $PfxPassword = $env:NETX_SIGN_PFX_PASSWORD }
}
if (-not $Thumbprint -and -not $PfxPath) {
throw "provide -Thumbprint or -PfxPath (or NETX_SIGN_THUMBPRINT / NETX_SIGN_PFX)"
}
$resolved = @()
foreach ($pattern in $Files) {
$resolved += @(Resolve-Path -Path $pattern -ErrorAction Stop)
}
if ($resolved.Count -eq 0) { throw "no_files_to_sign" }
foreach ($f in $resolved) {
$path = $f.Path
Write-Host "==> Signing $path"
$args = @(
"sign", "/fd", "SHA256", "/td", "SHA256", "/tr", $TimestampUrl,
"/d", $Description
)
if ($PfxPath) {
$args += @("/f", $PfxPath)
if ($PfxPassword) { $args += @("/p", $PfxPassword) }
} else {
$args += @("/sha1", $Thumbprint)
}
$args += $path
& $signtool @args
if ($LASTEXITCODE -ne 0) { throw "sign_failed: $path" }
& $signtool verify /pa $path
if ($LASTEXITCODE -ne 0) { throw "verify_failed: $path" }
Write-Host " OK" -ForegroundColor Green
}
Write-Host "==> Done. Without a trusted CA certificate, Windows SmartScreen may still warn."