# build-msi.ps1 $ErrorActionPreference = "Stop" $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { Start-Process powershell -Verb RunAs -ArgumentList "-NoExit -ExecutionPolicy Bypass -File `"$PSCommandPath`"" exit } Set-Location $PSScriptRoot Write-Host "=== 1. CAI DAT WIX TOOLSET ===" -ForegroundColor Cyan try { dotnet new tool-manifest --force 2>$null dotnet tool install wix --version 4.0.4 2>$null } catch {} Write-Host "`n=== 2. LAY CERTIFICATE DE KY ===" -ForegroundColor Cyan $cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -match "Tailscale-Custom" -and $_.HasPrivateKey } | Sort-Object NotAfter -Descending | Select-Object -First 1 if (-not $cert) { Write-Host " Khong tim thay cert, tao moi..." -ForegroundColor Yellow $cert = New-SelfSignedCertificate -Subject "CN=Tailscale-Custom, O=SoftsBusiness, C=VN" ` -Type CodeSigningCert -CertStoreLocation "Cert:\LocalMachine\My" ` -NotAfter (Get-Date).AddYears(5) # Trust cert $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") $rootStore.Open("ReadWrite") $rootStore.Add($cert) $rootStore.Close() # Also add to TrustedPublisher $pubStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine") $pubStore.Open("ReadWrite") $pubStore.Add($cert) $pubStore.Close() Write-Host " Da tao va trust cert: $($cert.Thumbprint)" } Write-Host " Dung cert: $($cert.Thumbprint)" Write-Host "`n=== 3. KY CAC FILE EXE TRONG \DIST ===" -ForegroundColor Cyan $distFiles = @("tailscaled.exe", "tailscale.exe", "tailscale-tray.exe") foreach ($name in $distFiles) { $path = Join-Path $PSScriptRoot "dist\$name" if (Test-Path $path) { try { $r = Set-AuthenticodeSignature -FilePath $path -Certificate $cert -HashAlgorithm SHA256 Write-Host " $name => $($r.Status)" } catch { Write-Host " $name => SKIP (khong ky duoc: $($_.Exception.Message))" -ForegroundColor Yellow } } else { Write-Warning "Khong tim thay file: $path" } } Write-Host "`n=== 4. BUILD FILE MSI ===" -ForegroundColor Cyan $msiPath = Join-Path $PSScriptRoot "Tailscale-Custom-Setup.msi" Remove-Item $msiPath -ErrorAction SilentlyContinue dotnet wix build "$PSScriptRoot\Setup.wxs" -out $msiPath if (-not (Test-Path $msiPath)) { Write-Error "BUILD THAT BAI! Khong tao duoc file MSI." exit 1 } $msiSize = [math]::Round((Get-Item $msiPath).Length / 1MB, 1) Write-Host " Da tao thanh cong: $msiPath ($msiSize MB)" -ForegroundColor Green Write-Host "`n=== 5. KY FILE MSI ===" -ForegroundColor Cyan try { $r = Set-AuthenticodeSignature -FilePath $msiPath -Certificate $cert -HashAlgorithm SHA256 Write-Host " Trang thai ky MSI: $($r.Status)" -ForegroundColor Green } catch { Write-Host " SKIP ky MSI (khong ky duoc: $($_.Exception.Message))" -ForegroundColor Yellow } Write-Host "`nHOAN TAT! File cai dat: $msiPath" -ForegroundColor Yellow