build_installer.ps1 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. $ErrorActionPreference = 'Stop'
  2. Add-Type -AssemblyName System.IO.Compression
  3. Add-Type -AssemblyName System.IO.Compression.FileSystem
  4. $repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..')
  5. $projectDir = Join-Path $repoRoot 'ComputerShopWpf'
  6. $binDir = Join-Path $projectDir 'bin\Debug'
  7. $databaseDir = Join-Path $projectDir 'Database'
  8. $buildDir = Join-Path $repoRoot 'Installer\build'
  9. $packageDir = Join-Path $buildDir 'package'
  10. $payloadZip = Join-Path $buildDir 'payload.zip'
  11. $stubExe = Join-Path $buildDir 'ComputerShopWpf_Setup.stub.exe'
  12. $setupPath = Join-Path (Resolve-Path 'outputs') 'ComputerShopWpf_Setup.exe'
  13. $sourcePath = Join-Path $PSScriptRoot 'SetupStub.cs'
  14. $cscPath = Join-Path $env:WINDIR 'Microsoft.NET\Framework\v4.0.30319\csc.exe'
  15. $marker = [System.Text.Encoding]::ASCII.GetBytes('CSWPF_SETUP_PAYLOAD_V1')
  16. $resolvedRepo = [System.IO.Path]::GetFullPath($repoRoot.Path)
  17. $resolvedBuild = [System.IO.Path]::GetFullPath($buildDir)
  18. if (-not $resolvedBuild.StartsWith($resolvedRepo, [System.StringComparison]::OrdinalIgnoreCase)) {
  19. throw "Refusing to clean outside repository: $resolvedBuild"
  20. }
  21. if (-not (Test-Path -LiteralPath $cscPath)) {
  22. throw "C# compiler was not found at $cscPath"
  23. }
  24. if (-not (Test-Path -LiteralPath (Join-Path $binDir 'ComputerShopWpf.exe'))) {
  25. throw "Build output was not found. Rebuild the solution first: $binDir"
  26. }
  27. if (Test-Path -LiteralPath $buildDir) {
  28. Remove-Item -LiteralPath $buildDir -Recurse -Force
  29. }
  30. New-Item -ItemType Directory -Path $packageDir | Out-Null
  31. New-Item -ItemType Directory -Path (Join-Path $packageDir 'Database') | Out-Null
  32. Get-ChildItem -LiteralPath $binDir -File |
  33. Where-Object { $_.Extension -in @('.exe', '.config', '.dll') } |
  34. Copy-Item -Destination $packageDir -Force
  35. Copy-Item -LiteralPath (Join-Path $repoRoot 'README.md') -Destination $packageDir -Force
  36. Copy-Item -LiteralPath (Join-Path $databaseDir 'create_database.sql') -Destination (Join-Path $packageDir 'Database') -Force
  37. Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'uninstall.ps1') -Destination $packageDir -Force
  38. if (Test-Path -LiteralPath $payloadZip) {
  39. Remove-Item -LiteralPath $payloadZip -Force
  40. }
  41. $zip = [System.IO.Compression.ZipFile]::Open($payloadZip, [System.IO.Compression.ZipArchiveMode]::Create)
  42. try {
  43. Get-ChildItem -LiteralPath $packageDir -Recurse -File | ForEach-Object {
  44. $relative = $_.FullName.Substring($packageDir.Length + 1).Replace('\', '/')
  45. [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
  46. $zip,
  47. $_.FullName,
  48. $relative,
  49. [System.IO.Compression.CompressionLevel]::Optimal) | Out-Null
  50. }
  51. }
  52. finally {
  53. $zip.Dispose()
  54. }
  55. & $cscPath `
  56. /nologo `
  57. /target:winexe `
  58. /platform:anycpu `
  59. /out:$stubExe `
  60. /reference:System.Windows.Forms.dll `
  61. /reference:System.Drawing.dll `
  62. /reference:System.IO.Compression.dll `
  63. /reference:System.IO.Compression.FileSystem.dll `
  64. $sourcePath
  65. if ($LASTEXITCODE -ne 0) {
  66. throw "C# installer stub compilation failed with exit code $LASTEXITCODE"
  67. }
  68. $stubBytes = [System.IO.File]::ReadAllBytes($stubExe)
  69. $payloadBytes = [System.IO.File]::ReadAllBytes($payloadZip)
  70. $lengthBytes = [System.BitConverter]::GetBytes([Int64]$payloadBytes.Length)
  71. if (Test-Path -LiteralPath $setupPath) {
  72. Remove-Item -LiteralPath $setupPath -Force
  73. }
  74. $out = [System.IO.File]::Open($setupPath, [System.IO.FileMode]::CreateNew, [System.IO.FileAccess]::Write)
  75. try {
  76. $out.Write($stubBytes, 0, $stubBytes.Length)
  77. $out.Write($payloadBytes, 0, $payloadBytes.Length)
  78. $out.Write($lengthBytes, 0, $lengthBytes.Length)
  79. $out.Write($marker, 0, $marker.Length)
  80. }
  81. finally {
  82. $out.Dispose()
  83. }
  84. Get-Item -LiteralPath $setupPath | Select-Object FullName, Length, LastWriteTime