[CmdletBinding()] param( [string]$OutputPath = ".\dist\MrTrust.exe" ) $ErrorActionPreference = "Stop" function Resolve-FullPath { param([Parameter(Mandatory)][string]$Path) $executionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) } $root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path) $sourcePath = Join-Path $root "src\MrTrustLauncher.cs" $iconPath = Join-Path $root "assets\MrTrust.ico" $resolvedOutputPath = Resolve-FullPath $OutputPath $outputDirectory = Split-Path -Parent $resolvedOutputPath $payloadFiles = @( @{ Path = "MrTrust.ps1"; ResourceName = "MrTrust.Payload.MrTrust.ps1" }, @{ Path = "scripts\Build-MrTrustExe.ps1"; ResourceName = "MrTrust.Payload.scripts.Build-MrTrustExe.ps1" }, @{ Path = "scripts\Install-MrTrust.ps1"; ResourceName = "MrTrust.Payload.scripts.Install-MrTrust.ps1" }, @{ Path = "scripts\New-MrTrustCertificate.ps1"; ResourceName = "MrTrust.Payload.scripts.New-MrTrustCertificate.ps1" }, @{ Path = "scripts\New-MrTrustIcon.ps1"; ResourceName = "MrTrust.Payload.scripts.New-MrTrustIcon.ps1" }, @{ Path = "scripts\New-MrTrustRelease.ps1"; ResourceName = "MrTrust.Payload.scripts.New-MrTrustRelease.ps1" }, @{ Path = "scripts\Sign-MrTrustProject.ps1"; ResourceName = "MrTrust.Payload.scripts.Sign-MrTrustProject.ps1" }, @{ Path = "scripts\Start-MrTrustGui.ps1"; ResourceName = "MrTrust.Payload.scripts.Start-MrTrustGui.ps1" }, @{ Path = "scripts\Uninstall-MrTrust.ps1"; ResourceName = "MrTrust.Payload.scripts.Uninstall-MrTrust.ps1" }, @{ Path = "assets\MrTrust.ico"; ResourceName = "MrTrust.Payload.assets.MrTrust.ico" }, @{ Path = "assets\certificates\MrSphay-LocalTrust-Root.cer"; ResourceName = "MrTrust.Payload.assets.certificates.MrSphay-LocalTrust-Root.cer" }, @{ Path = "assets\certificates\MrSphay-CodeSigning.cer"; ResourceName = "MrTrust.Payload.assets.certificates.MrSphay-CodeSigning.cer" }, @{ Path = "assets\certificates\thumbprints.txt"; ResourceName = "MrTrust.Payload.assets.certificates.thumbprints.txt" } ) if (-not (Test-Path -LiteralPath $sourcePath)) { throw "Launcher source not found: $sourcePath" } if (-not (Test-Path -LiteralPath $iconPath)) { & (Join-Path $root "scripts\New-MrTrustIcon.ps1") -OutputPath $iconPath } foreach ($payloadFile in $payloadFiles) { $payloadPath = Join-Path $root $payloadFile.Path if (-not (Test-Path -LiteralPath $payloadPath)) { throw "Payload file not found: $payloadPath" } } New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null $compilerCandidates = @( "$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\csc.exe", "$env:WINDIR\Microsoft.NET\Framework\v4.0.30319\csc.exe" ) $compiler = $compilerCandidates | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1 if (-not $compiler) { throw "csc.exe was not found. Run this build on a Windows Gitea runner with .NET Framework installed." } $compilerArguments = @( "/nologo", "/target:winexe", "/optimize+", "/platform:anycpu", "/out:$resolvedOutputPath", "/win32icon:$iconPath", "/reference:System.Windows.Forms.dll", "/reference:System.Drawing.dll" ) foreach ($payloadFile in $payloadFiles) { $payloadPath = Join-Path $root $payloadFile.Path $compilerArguments += "/resource:$payloadPath,$($payloadFile.ResourceName)" } $compilerArguments += $sourcePath & $compiler @compilerArguments if ($LASTEXITCODE -ne 0) { throw "csc.exe failed with exit code $LASTEXITCODE." } Write-Host "Created standalone EXE:" Write-Host " $resolvedOutputPath"