Files
netdesk/native/packaging/build-installer.ps1
T

146 lines
7.1 KiB
PowerShell

<#
NetDesk by Akronlogic -- INSTALLER build script.
1. Runs build-portable.ps1 to build the release viewer and stage the files
(dist\NetDesk-Portable\).
2. Detects makensis (NSIS). If found, compiles netdesk.nsi into
dist\NetDesk-Setup-win64.exe. If NOT found, prints install instructions
and still leaves the staging folder ready.
3. Code-signs NetDesk.exe (in the staging folder) and the setup .exe via
certs\sign-release.ps1, when signing is available.
Usage:
powershell -ExecutionPolicy Bypass -File build-installer.ps1
powershell -ExecutionPolicy Bypass -File build-installer.ps1 -SkipBuild
powershell -ExecutionPolicy Bypass -File build-installer.ps1 -NoSign
powershell -ExecutionPolicy Bypass -File build-installer.ps1 -Thumbprint <THUMB>
#>
[CmdletBinding()]
param(
[string]$MingwBin = "C:\mingw-netdesk\mingw64\bin",
[string]$Thumbprint = "YOUR_CODE_SIGNING_CERT_THUMBPRINT",
[switch]$SkipBuild,
[switch]$NoSign
)
$ErrorActionPreference = "Stop"
# ---- paths -----------------------------------------------------------------
$PkgDir = $PSScriptRoot
$RootDir = Split-Path -Parent $PkgDir
$DistDir = Join-Path $PkgDir "dist"
$StageDir = Join-Path $DistDir "NetDesk-Portable"
$NsiScript = Join-Path $PkgDir "netdesk.nsi"
$SetupExe = Join-Path $DistDir "NetDesk-Setup-win64.exe"
$SignPs1 = Join-Path $RootDir "certs\sign-release.ps1"
$BrandIco = Join-Path $PkgDir "netdesk.ico" # branded setup-exe icon
$AssetIco = Join-Path $RootDir "assets\icon.ico" # source NetDesk mark
Write-Host "=== NetDesk installer build (Akronlogic) ===" -ForegroundColor Cyan
# ---- 1. stage via build-portable.ps1 --------------------------------------
Write-Host "`n[1/4] staging portable payload" -ForegroundColor Yellow
$portableArgs = @{ MingwBin = $MingwBin }
if ($SkipBuild) { $portableArgs.SkipBuild = $true }
& (Join-Path $PkgDir "build-portable.ps1") @portableArgs
if ($LASTEXITCODE) { throw "build-portable.ps1 failed (exit $LASTEXITCODE)" }
if (-not (Test-Path $StageDir)) { throw "staging folder missing: $StageDir" }
# ---- sign the staged NetDesk.exe BEFORE packaging it into the installer ----
function Invoke-Sign([string[]]$Files) {
if ($NoSign) { Write-Host " -NoSign set: skipping signing." -ForegroundColor DarkYellow; return }
if (-not (Test-Path $SignPs1)) { Write-Host " signing helper not found ($SignPs1) -- skipping." -ForegroundColor DarkYellow; return }
$signtool = Get-Command signtool.exe -ErrorAction SilentlyContinue
foreach ($f in $Files) {
if (-not (Test-Path $f)) { continue }
Write-Host " signing: $f" -ForegroundColor Gray
try {
if ($signtool) {
& $signtool.Source sign /sha1 $Thumbprint /fd SHA256 /tr "http://timestamp.sectigo.com" /td SHA256 "$f"
if ($LASTEXITCODE) { Write-Host " signtool returned $LASTEXITCODE (continuing)" -ForegroundColor DarkYellow }
} else {
# Fall back to Set-AuthenticodeSignature via the project helper logic.
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Thumbprint -eq $Thumbprint } | Select-Object -First 1
if (-not $cert) { Write-Host " cert $Thumbprint not in CurrentUser\My -- skipping." -ForegroundColor DarkYellow; continue }
$r = Set-AuthenticodeSignature -FilePath $f -Certificate $cert -HashAlgorithm SHA256 -TimestampServer "http://timestamp.sectigo.com"
Write-Host (" sign: {0}" -f $r.Status) -ForegroundColor Gray
}
} catch {
Write-Host " signing failed: $($_.Exception.Message) (continuing)" -ForegroundColor DarkYellow
}
}
}
Write-Host "`n[2/4] signing staged NetDesk.exe" -ForegroundColor Yellow
# Run the official project helper on the release tree (signs netdesk-viewer.exe
# etc. exactly as Akronlogic ships them). Non-fatal if the cert isn't present.
if (-not $NoSign -and (Test-Path $SignPs1)) {
try {
& powershell -NoProfile -ExecutionPolicy Bypass -File $SignPs1 -Thumbprint $Thumbprint
} catch {
Write-Host " sign-release.ps1 note: $($_.Exception.Message) (continuing)" -ForegroundColor DarkYellow
}
}
# The staged NetDesk.exe is a renamed COPY, so it needs its own signature using
# the same certificate + timestamp mechanism that sign-release.ps1 uses.
Invoke-Sign @( (Join-Path $StageDir "NetDesk.exe") )
# Re-zip the portable artifact so it, too, ships the now-signed NetDesk.exe
# (build-portable.ps1 zipped the staging folder before this signing step).
if (-not $NoSign) {
$zip = Join-Path $DistDir "NetDesk-Portable-win64.zip"
if (Test-Path $zip) { Remove-Item $zip -Force }
Compress-Archive -Path (Join-Path $StageDir "*") -DestinationPath $zip -CompressionLevel Optimal
Write-Host " re-zipped portable with signed NetDesk.exe -> $zip" -ForegroundColor Gray
}
# ---- 3. compile the installer with makensis -------------------------------
Write-Host "`n[3/4] locating makensis (NSIS)" -ForegroundColor Yellow
$makensis = Get-Command makensis.exe -ErrorAction SilentlyContinue
if (-not $makensis) {
foreach ($p in @("$env:ProgramFiles\NSIS\makensis.exe", "${env:ProgramFiles(x86)}\NSIS\makensis.exe")) {
if (Test-Path $p) { $makensis = Get-Item $p; break }
}
}
if (-not $makensis) {
Write-Host ""
Write-Host "makensis (NSIS) is NOT installed -- the installer .exe was NOT built." -ForegroundColor Red
Write-Host "The portable zip and the installer staging folder are ready." -ForegroundColor Red
Write-Host ""
Write-Host "Install NSIS, then re-run this script:" -ForegroundColor Yellow
Write-Host " winget install --id NSIS.NSIS -e"
Write-Host " or download from https://nsis.sourceforge.io/Download"
Write-Host ""
Write-Host "After installing, build the installer manually with:" -ForegroundColor Yellow
Write-Host (" makensis /DSTAGEDIR={0} /DOUTFILE={1} `"{2}`"" -f $StageDir, $SetupExe, $NsiScript)
exit 0
}
Write-Host " found: $($makensis.Source)" -ForegroundColor Gray
if (Test-Path $SetupExe) { Remove-Item $SetupExe -Force }
# Brand the setup .exe with the green NetDesk icon (copy the asset next to the
# .nsi and pass its absolute path as /DBRANDICON).
$nsisArgs = @("/DSTAGEDIR=$StageDir", "/DOUTFILE=$SetupExe")
if (Test-Path $AssetIco) {
Copy-Item $AssetIco $BrandIco -Force
$nsisArgs += "/DBRANDICON=$BrandIco"
Write-Host " branding setup icon: $BrandIco" -ForegroundColor Gray
} else {
Write-Host " asset icon not found ($AssetIco) -- setup will use the default NSIS icon." -ForegroundColor DarkYellow
}
$nsisArgs += "$NsiScript"
& $makensis.Source @nsisArgs
if ($LASTEXITCODE) { throw "makensis failed (exit $LASTEXITCODE)" }
if (-not (Test-Path $SetupExe)) { throw "makensis reported success but $SetupExe is missing" }
# ---- 4. sign the setup .exe ------------------------------------------------
Write-Host "`n[4/4] signing the setup installer" -ForegroundColor Yellow
Invoke-Sign @( $SetupExe )
$si = Get-Item $SetupExe
Write-Host "`nInstaller build complete." -ForegroundColor Green
Write-Host (" setup : {0}" -f $si.FullName)
Write-Host (" size : {0:N0} bytes ({1:N2} MB)" -f $si.Length, ($si.Length/1MB))