Files
pebrel/scripts/windows-msix.ps1
Kuddev bf2ed9af9b feat(mobile): integrate remote terminal, SSH and reader workflows (#343)
Integrate the Android client with native desktop pairing, remote terminal and SSH/SFTP sessions, keyboard controls, file reading and Agent conversations. Preserve authenticated connection ownership and per-device input permissions.

Validation: all ten required GitHub checks passed, including five native test platforms and both macOS release workspace checks.
2026-09-29 20:09:00 +08:00

85 lines
4.7 KiB
PowerShell

# MSIX 清单与静态资源准备;构建和发布仍由调用方持有,不加载或执行插件。
function Assert-PebrelMsixIdentity {
param([string] $IdentityName, [string] $Publisher, [string] $PublisherDisplayName, [string] $Version)
if ($IdentityName -cnotmatch '^[A-Za-z0-9.-]{3,50}$' -or $IdentityName -match '^(Microsoft|Windows)\.') {
throw 'Use the exact Package/Identity/Name reserved in Partner Center (3-50 ASCII letters, numbers, dots or hyphens).'
}
if ([string]::IsNullOrWhiteSpace($Publisher) -or $Publisher -notmatch '(^|,)\s*CN=') {
throw 'Publisher must be the X.500 identity from Partner Center, including CN=.'
}
$null = [System.Security.Cryptography.X509Certificates.X500DistinguishedName]::new($Publisher)
if ([string]::IsNullOrWhiteSpace($PublisherDisplayName) -or $PublisherDisplayName.Length -gt 256) {
throw 'PublisherDisplayName must contain 1-256 characters.'
}
if ($Version -notmatch '^[0-9]+\.[0-9]+\.[0-9]+$') { throw 'MSIX requires a stable major.minor.patch version.' }
$parts = @($Version.Split('.') | ForEach-Object { [int] $_ })
if ($parts[0] -lt 1 -or @($parts | Where-Object { $_ -gt 65535 }).Count -gt 0) {
throw 'MSIX version components must fit UInt16, with a nonzero major version.'
}
}
function New-PebrelMsixLayout {
param(
[Parameter(Mandatory = $true)][string] $Root,
[Parameter(Mandatory = $true)][string] $IdentityName,
[Parameter(Mandatory = $true)][string] $Publisher,
[Parameter(Mandatory = $true)][string] $PublisherDisplayName,
[Parameter(Mandatory = $true)][string] $Version,
[ValidateSet('x64', 'arm64')][string] $Architecture = 'x64'
)
Assert-PebrelMsixIdentity $IdentityName $Publisher $PublisherDisplayName $Version
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
if (-not (Test-Path -LiteralPath $Root -PathType Container)) { throw "Missing MSIX layout: $Root" }
. (Join-Path $PSScriptRoot 'windows-package-architecture.ps1')
Assert-WindowsPackageArchitecture -Root $Root -RuntimeDirectory (Join-Path $Root 'runtime') -Architecture $Architecture
$template = [IO.File]::ReadAllText((Join-Path $repo 'packaging/windows/AppxManifest.xml'), [Text.Encoding]::UTF8)
$values = @{
IDENTITY_NAME = $IdentityName
PUBLISHER = $Publisher
PUBLISHER_DISPLAY_NAME = $PublisherDisplayName
VERSION = "$Version.0"
ARCHITECTURE = $Architecture
}
# MatchEvaluator 防止用户字段中的 @TOKEN@ 被第二次替换;XML 值始终转义。
$manifest = [regex]::Replace($template, '@([A-Z_]+)@', [Text.RegularExpressions.MatchEvaluator] {
param($match)
$key = $match.Groups[1].Value
if (-not $values.ContainsKey($key)) { throw "Unknown manifest token: $key" }
[Security.SecurityElement]::Escape($values[$key])
})
$null = [xml] $manifest
$manifestPath = Join-Path $Root 'AppxManifest.xml'
[IO.File]::WriteAllText($manifestPath, $manifest, [Text.UTF8Encoding]::new($false))
# 缩放现有产品图标,不另造品牌素材;System.Drawing 仅在 Windows 打包进程内使用。
Add-Type -AssemblyName System.Drawing
$assets = Join-Path $Root 'Assets'
New-Item -ItemType Directory -Path $assets -Force | Out-Null
$source = [Drawing.Image]::FromFile((Join-Path $repo 'extra/logo/nebula-titanium.png'))
try {
foreach ($entry in @{'StoreLogo.png'=50; 'Square44x44Logo.png'=44; 'Square150x150Logo.png'=150}.GetEnumerator()) {
$bitmap = [Drawing.Bitmap]::new([int]$entry.Value, [int]$entry.Value)
$graphics = [Drawing.Graphics]::FromImage($bitmap)
try {
$graphics.InterpolationMode = [Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$graphics.DrawImage($source, 0, 0, [int]$entry.Value, [int]$entry.Value)
$bitmap.Save((Join-Path $assets $entry.Key), [Drawing.Imaging.ImageFormat]::Png)
} finally { $graphics.Dispose(); $bitmap.Dispose() }
}
} finally { $source.Dispose() }
}
function Find-PebrelMakeAppx {
$command = Get-Command makeappx.exe -ErrorAction SilentlyContinue
if ($command) { return $command.Source }
$kits = Join-Path ${env:ProgramFiles(x86)} 'Windows Kits/10/bin'
$sdk = Get-ChildItem -LiteralPath $kits -Directory -ErrorAction Stop |
Where-Object { $_.Name -match '^10\.0\.[0-9]+\.0$' } |
Sort-Object { [version] $_.Name } -Descending
foreach ($version in $sdk) {
$candidate = Join-Path $version.FullName 'x64/makeappx.exe'
if (Test-Path -LiteralPath $candidate -PathType Leaf) { return $candidate }
}
throw 'Install the Windows 10/11 SDK packaging tools, or supply -MakeAppxPath.'
}