Public/Export-SignedExecutable.ps1
<#
.SYNOPSIS Signs executable files using a specified signing profile. .DESCRIPTION The Export-SignedExecutable function signs one or more executable files using the configuration from a previously created signing profile. It supports both local certificate signing and Azure Key Vault signing, automatically selecting the appropriate signing method based on the profile type. The function validates file paths and extensions before attempting to sign. .PARAMETER ProfileName Specifies the name of the signing profile to use for signing operations. The profile must exist and be properly configured. Use Add-SignProfile to create profiles. .PARAMETER Files Specifies an array of file paths to sign. Files must exist and have the .exe extension. This parameter accepts pipeline input, allowing you to pipe file objects from other commands. .INPUTS System.String[]. You can pipe file paths to Export-SignedExecutable. .OUTPUTS None. This function does not return objects but signs the specified files. .EXAMPLE Export-SignedExecutable -ProfileName "Production" -Files "C:\MyApp\MyApp.exe" Signs a single executable file using the "Production" profile. .EXAMPLE Export-SignedExecutable -ProfileName "Production" -Files @("App1.exe", "App2.exe", "App3.exe") Signs multiple executable files using the "Production" profile. .EXAMPLE Get-ChildItem "C:\Build\Output\*.exe" | Export-SignedExecutable -ProfileName "Production" Uses pipeline input to sign all .exe files in the specified directory. .EXAMPLE $filesToSign = Get-ChildItem "C:\MyApps" -Recurse -Filter "*.exe" $filesToSign | Export-SignedExecutable -ProfileName "LocalCert" Finds all executable files recursively in a directory tree and signs them using a local certificate profile. .EXAMPLE # Sign files with error handling try { Export-SignedExecutable -ProfileName "AzureKV" -Files "MyApp.exe" Write-Host "Signing completed successfully" } catch { Write-Error "Signing failed: $($_.Exception.Message)" } Example with error handling to catch signing failures. .EXAMPLE # Batch signing with filtering Get-ChildItem "C:\Build" -Recurse | Where-Object { $_.Extension -eq '.exe' -and $_.Length -gt 1MB } | Export-SignedExecutable -ProfileName "Production" Signs only executable files larger than 1MB from a build directory. .NOTES File Name : Export-SignedExecutable.ps1 Author : GrafGenerator Prerequisite : PowerShell 5.1 or later Copyright 2025 : GrafGenerator This function requires: - A valid signing profile created with Add-SignProfile - Appropriate signing tools (SignTool.exe for local, AzureSignTool.exe for Azure) - Valid certificates accessible through the configured profile - Files must have .exe extension and exist on the file system The function will skip files that don't exist or don't have the correct extension, logging warnings for each skipped file. .LINK Add-SignProfile .LINK Update-SignProfile .LINK Remove-SignProfile .LINK https://github.com/GrafGenerator/pwsh-sign-module #> function Export-SignedExecutable { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$ProfileName, [Parameter(Mandatory, ValueFromPipeline)] [string[]]$Files ) begin { $config = Get-Config if (-not $config.profiles.ContainsKey($ProfileName)) { throw "Profile '$ProfileName' not found" } $profilePath = $config.profiles[$ProfileName].path $signingProfile = Get-Content $profilePath | ConvertFrom-Json $scriptName = if ($signingProfile.type -eq 'local') { 'local-sign.ps1' } else { 'azure-sign.ps1' } $scriptPath = Join-Path $PSScriptRoot "..\\Scripts\\$scriptName" if (-not (Test-Path $scriptPath)) { throw "Signing script not found: $scriptPath" } } process { foreach ($file in $Files) { if (-not (Test-Path $file)) { Write-Warning "File not found: $file" continue } if ([System.IO.Path]::GetExtension($file) -ne '.exe') { Write-Warning "File is not an executable: $file" continue } } & $scriptPath -ProfilePath $profilePath -Files $Files } } |