<# 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 #> [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))