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.
85 lines
4.7 KiB
PowerShell
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.'
|
|
}
|