mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
* empowering users to maximize OOBE to their heart desire (#37823) empowering users to maximize to their heart desire * resume main * Trust selfsign cert in localmachine\root to make msix available * minor fix * retry signing --------- Co-authored-by: Clint Rutkas <clint@rutkas.com>
180 lines
5.9 KiB
PowerShell
180 lines
5.9 KiB
PowerShell
#https://learn.microsoft.com/en-us/windows/msix/package/signing-known-issues
|
|
# 1. Build the powertoys as usual.
|
|
# 2. Call this script to sign the msix package.
|
|
# First time run needs admin permission to trust the certificate.
|
|
|
|
param (
|
|
[string]$architecture = "x64", # Default to x64 if not provided
|
|
[string]$buildConfiguration = "Debug" # Default to Debug if not provided
|
|
)
|
|
|
|
$signToolPath = $null
|
|
$kitsRootPaths = @(
|
|
"C:\Program Files (x86)\Windows Kits\10\bin",
|
|
"C:\Program Files\Windows Kits\10\bin"
|
|
)
|
|
|
|
$signToolAvailable = Get-Command "signtool" -ErrorAction SilentlyContinue
|
|
if ($signToolAvailable) {
|
|
Write-Host "SignTool is available in the system PATH."
|
|
$signToolPath = "signtool"
|
|
}
|
|
else {
|
|
Write-Host "Searching for latest SignTool matching architecture: $architecture"
|
|
|
|
foreach ($root in $kitsRootPaths) {
|
|
if (Test-Path $root) {
|
|
$versions = Get-ChildItem -Path $root -Directory | Where-Object {
|
|
$_.Name -match '^\d+\.\d+\.\d+\.\d+$'
|
|
} | Sort-Object Name -Descending
|
|
|
|
foreach ($version in $versions) {
|
|
$candidatePath = Join-Path -Path $version.FullName -ChildPath "x86"
|
|
$exePath = Join-Path -Path $candidatePath -ChildPath "signtool.exe"
|
|
if (Test-Path $exePath) {
|
|
Write-Host "Found SignTool at: $exePath"
|
|
$signToolPath = $exePath
|
|
break
|
|
}
|
|
}
|
|
|
|
if ($signToolPath) { break }
|
|
}
|
|
}
|
|
|
|
if (!$signToolPath) {
|
|
Write-Host "SignTool not found. Please ensure Windows SDK is installed."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
Write-Host "`nUsing SignTool: $signToolPath"
|
|
|
|
# Set the certificate subject and the ECDSA curve
|
|
$certSubject = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
|
|
|
# Check if the certificate already exists in the current user's certificate store
|
|
$existingCert = Get-ChildItem -Path Cert:\CurrentUser\My |
|
|
Where-Object { $_.Subject -eq $certSubject } |
|
|
Sort-Object NotAfter -Descending |
|
|
Select-Object -First 1
|
|
|
|
if ($existingCert) {
|
|
# If the certificate exists, use the existing certificate
|
|
Write-Host "Certificate already exists, using the existing certificate"
|
|
$cert = $existingCert
|
|
}
|
|
else {
|
|
# If the certificate doesn't exist, create a new self-signed certificate
|
|
Write-Host "Certificate does not exist, creating a new certificate..."
|
|
$cert = New-SelfSignedCertificate -Subject $certSubject `
|
|
-CertStoreLocation "Cert:\CurrentUser\My" `
|
|
-KeyAlgorithm RSA `
|
|
-Type CodeSigningCert `
|
|
-HashAlgorithm SHA256
|
|
}
|
|
|
|
function Import-And-VerifyCertificate {
|
|
param (
|
|
[string]$cerPath,
|
|
[string]$storePath
|
|
)
|
|
|
|
$thumbprint = (Get-PfxCertificate -FilePath $cerPath).Thumbprint
|
|
|
|
# ✅ Step 1: Check if already exists in store
|
|
$existingCert = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint }
|
|
|
|
if ($existingCert) {
|
|
Write-Host "✅ Certificate already exists in $storePath"
|
|
return $true
|
|
}
|
|
|
|
# 🚀 Step 2: Try to import if not already there
|
|
try {
|
|
$null = Import-Certificate -FilePath $cerPath -CertStoreLocation $storePath -ErrorAction Stop
|
|
}
|
|
catch {
|
|
Write-Warning "❌ Failed to import certificate to $storePath : $_"
|
|
return $false
|
|
}
|
|
|
|
# 🔁 Step 3: Verify again
|
|
$imported = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint }
|
|
|
|
if ($imported) {
|
|
Write-Host "✅ Certificate successfully imported to $storePath"
|
|
return $true
|
|
}
|
|
else {
|
|
Write-Warning "❌ Certificate not found in $storePath after import"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
$cerPath = "$env:TEMP\temp_cert.cer"
|
|
Export-Certificate -Cert $cert -FilePath $cerPath -Force
|
|
# used for sign code/msix
|
|
# CurrentUser\TrustedPeople
|
|
if (-not (Import-And-VerifyCertificate -cerPath $cerPath -storePath "Cert:\CurrentUser\TrustedPeople")) {
|
|
exit 1
|
|
}
|
|
|
|
# CurrentUser\Root
|
|
if (-not (Import-And-VerifyCertificate -cerPath $cerPath -storePath "Cert:\CurrentUser\Root")) {
|
|
exit 1
|
|
}
|
|
|
|
# LocalMachine\Root
|
|
if (-not (Import-And-VerifyCertificate -cerPath $cerPath -storePath "Cert:\LocalMachine\Root")) {
|
|
Write-Warning "⚠️ Failed to import to LocalMachine\Root (admin may be required)"
|
|
exit 1
|
|
}
|
|
|
|
|
|
# Output the thumbprint of the certificate (to confirm which certificate is being used)
|
|
Write-Host "Using certificate with thumbprint: $($cert.Thumbprint)"
|
|
|
|
|
|
$rootDirectory = (Split-Path -Parent(Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)))
|
|
|
|
# Dynamically build the directory path based on architecture and build configuration
|
|
# $directoryPath = Join-Path $rootDirectory "$architecture\$buildConfiguration\WinUI3Apps\CmdPal\"
|
|
$directoryPath = Join-Path $rootDirectory "$architecture\$buildConfiguration\WinUI3Apps\CmdPal\"
|
|
|
|
if (-not (Test-Path $directoryPath)) {
|
|
Write-Error "Path to search for msix files does not exist: $directoryPath"
|
|
exit 1
|
|
}
|
|
|
|
Write-Host "Directory path to search for .msix and .appx files: $directoryPath"
|
|
|
|
# Get all .msix and .appx files from the specified directory
|
|
$filePaths = Get-ChildItem -Path $directoryPath -Recurse | Where-Object {
|
|
($_.Extension -eq ".msix" -or $_.Extension -eq ".appx") -and
|
|
($_.Name -like "*$architecture*")
|
|
}
|
|
|
|
if ($filePaths.Count -eq 0) {
|
|
Write-Host "No .msix or .appx files found in the directory."
|
|
}
|
|
else {
|
|
# Iterate through each file and sign it
|
|
foreach ($file in $filePaths) {
|
|
Write-Host "Signing file: $($file.FullName)"
|
|
|
|
# Use SignTool to sign the file
|
|
$signToolCommand = "& `"$signToolPath`" sign /sha1 $($cert.Thumbprint) /fd SHA256 /t http://timestamp.digicert.com `"$($file.FullName)`""
|
|
|
|
# Execute the sign command
|
|
try {
|
|
Invoke-Expression $signToolCommand
|
|
}
|
|
catch {
|
|
Write-Host "Error signing file $($file.Name): $_"
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Host "Signing process completed."
|