prepare-windows-installer.ps1 4.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. <# Compile the x86 DWM helper and raster assets embedded in the NSIS installer. #>
  2. [CmdletBinding()]
  3. param([string]$OutputDirectory, [switch]$TestProgress, [switch]$CompileProgressOnly)
  4. $ErrorActionPreference = 'Stop'
  5. $installerRoot = Join-Path $PSScriptRoot '../installer'
  6. if (-not $OutputDirectory) { $OutputDirectory = Join-Path $PSScriptRoot '../.desktop-build/targets/win-x64/installer-ui' }
  7. $output = [IO.Path]::GetFullPath($OutputDirectory)
  8. New-Item -ItemType Directory -Force $output | Out-Null
  9. $source = Join-Path $installerRoot 'window-frame.cpp'
  10. $library = Join-Path $output 'window-frame.dll'
  11. $vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio/Installer/vswhere.exe'
  12. if (-not (Test-Path -LiteralPath $vswhere)) { throw 'Windows installer preparation requires Visual Studio C++ Build Tools and a Windows SDK.' }
  13. $visualStudio = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
  14. if (-not $visualStudio) { throw 'Visual Studio C++ Build Tools are missing.' }
  15. $vcvars = Join-Path $visualStudio 'VC/Auxiliary/Build/vcvars32.bat'
  16. $compileScript = Join-Path $output 'compile-frame.cmd'
  17. $compileLines = @('@echo off', ('call "{0}" >nul' -f $vcvars), 'if errorlevel 1 exit /b %errorlevel%', ('cl /nologo /LD /MT /O1 /W4 /WX /EHsc "{0}" /Fo"{1}" /link /OUT:"{2}" /IMPLIB:"{3}" user32.lib comctl32.lib dwmapi.lib gdiplus.lib ole32.lib shell32.lib uuid.lib' -f $source, (Join-Path $output 'window-frame.obj'), $library, (Join-Path $output 'window-frame.lib')))
  18. [IO.File]::WriteAllLines($compileScript, $compileLines, [Text.Encoding]::Default)
  19. & $env:ComSpec /d /c $compileScript
  20. if ($LASTEXITCODE -ne 0) { throw 'Native installer helper compilation failed.' }
  21. if ($TestProgress -or $CompileProgressOnly) {
  22. $testSource = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../tests/windows-installer-progress.cpp'))
  23. $testExecutable = Join-Path $output 'progress-test.exe'
  24. $testScript = Join-Path $output 'compile-progress-test.cmd'
  25. [IO.File]::WriteAllLines($testScript, @('@echo off', ('call "{0}" >nul' -f $vcvars), 'if errorlevel 1 exit /b %errorlevel%', ('cl /nologo /MT /W4 /WX /EHsc "{0}" /Fo"{1}" /Fe"{2}"' -f $testSource, (Join-Path $output 'progress-test.obj'), $testExecutable)), [Text.Encoding]::Default)
  26. & $env:ComSpec /d /c $testScript
  27. if ($LASTEXITCODE -ne 0) { throw 'Progress test compilation failed.' }
  28. if ($TestProgress) {
  29. & $testExecutable
  30. if ($LASTEXITCODE -ne 0) { throw 'Progress timeline regression failed.' }
  31. }
  32. $presentationSource = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../tests/windows-installer-presentation.cpp'))
  33. $presentationExecutable = Join-Path $output 'presentation-test.exe'
  34. $presentationScript = Join-Path $output 'compile-presentation-test.cmd'
  35. [IO.File]::WriteAllLines($presentationScript, @('@echo off', ('call "{0}" >nul' -f $vcvars), 'if errorlevel 1 exit /b %errorlevel%', ('cl /nologo /MT /W4 /WX /EHsc "{0}" /Fo"{1}" /Fe"{2}" /link "{3}" user32.lib' -f $presentationSource, (Join-Path $output 'presentation-test.obj'), $presentationExecutable, (Join-Path $output 'window-frame.lib'))), [Text.Encoding]::Default)
  36. & $env:ComSpec /d /c $presentationScript
  37. if ($LASTEXITCODE -ne 0) { throw 'Installer presentation test compilation failed.' }
  38. if ($TestProgress) {
  39. & $presentationExecutable
  40. if ($LASTEXITCODE -ne 0) { throw 'Installer presentation regression failed.' }
  41. }
  42. }
  43. Add-Type -AssemblyName System.Drawing
  44. foreach ($asset in @('brand', 'brand-2x', 'brand-dark', 'brand-dark-2x', 'uninstaller-sidebar')) {
  45. $image = [Drawing.Image]::FromFile((Join-Path $installerRoot "assets/$asset.png"))
  46. try {
  47. $bitmap = [Drawing.Bitmap]::new($image.Width, $image.Height, [Drawing.Imaging.PixelFormat]::Format24bppRgb)
  48. try {
  49. $graphics = [Drawing.Graphics]::FromImage($bitmap)
  50. try {
  51. $background = if ($asset -like '*dark*') { [Drawing.Color]::FromArgb(21, 21, 23) } else { [Drawing.Color]::White }
  52. $graphics.Clear($background)
  53. $graphics.DrawImage($image, 0, 0, $image.Width, $image.Height)
  54. } finally { $graphics.Dispose() }
  55. $bitmap.Save((Join-Path $output "$asset.bmp"), [Drawing.Imaging.ImageFormat]::Bmp)
  56. } finally { $bitmap.Dispose() }
  57. } finally { $image.Dispose() }
  58. }
  59. Write-Output "Prepared native installer resources: $output"