|
#!/bin/pwsh
|
|
# File: Sign-Code.ps1
|
|
# Last-Modified: 2026-04-01T11:07:34-0400
|
|
# Locations:
|
|
# \\utility5\e$\CodeSign\Scripts
|
|
# Author: bgstack15
|
|
# Startdate: 2026-03-31
|
|
# Title: Sign-Code
|
|
# Project: Codesign
|
|
# Purpose: Functions for easily signing binaries on utility5
|
|
# History:
|
|
# Usage:
|
|
# As a library, . .\Sign-Code.ps1
|
|
# Or directly, ".\Sign-Code.ps1"
|
|
# References:
|
|
# https://www.scriptinglibrary.com/languages/powershell/how-to-modify-your-proxy-settings-with-powershell/
|
|
# https://4sysops.com/archives/how-to-create-an-open-file-folder-dialog-box-with-powershell/
|
|
# Improve:
|
|
# Dependencies:
|
|
# Cert loaded in Cert:\LocalMachine\My
|
|
# Documentation:
|
|
<#
|
|
.SYNOPSIS
|
|
Functions for easily signing binaries on the utility server.
|
|
|
|
.DESCRIPTION
|
|
This script provides functions to configure proxy settings, select files via a dialog,
|
|
sign binaries using signtool.exe, and move signed files to a destination folder.
|
|
It supports being dot-sourced as a library or run directly to invoke the signing process.
|
|
|
|
.NOTES
|
|
.USAGE
|
|
As a library (import functions for manual use):
|
|
. .\Sign-Code.ps1
|
|
|
|
Run directly (sign files from default or specified folders):
|
|
.\Sign-Code.ps1
|
|
|
|
.PARAMETER Set-Proxy
|
|
Configures the user's system proxy settings by modifying registry keys.
|
|
|
|
.PARAMETER Get-File-Dialog
|
|
Opens a Windows File Open dialog to select one or more files.
|
|
|
|
.PARAMETER Sign-File
|
|
Signs each file using signtool.exe and moves successfully signed files to a destination folder.
|
|
|
|
.PARAMETER Ask-Sign-Files
|
|
Main function to select files, and sign them.
|
|
|
|
.DEPENDENCIES
|
|
- Windows signtool.exe located at the specified path.
|
|
- Code signing certificate loaded in Cert:\LocalMachine\My.
|
|
- User has write permissions to destination folders.
|
|
|
|
.REFERENCES
|
|
- https://www.scriptinglibrary.com/languages/powershell/how-to-modify-your-proxy-settings-with-powershell/
|
|
- https://4sysops.com/archives/how-to-create-an-open-file-folder-dialog-box-with-powershell/
|
|
#>
|
|
|
|
#region Proxy Configuration Function
|
|
|
|
Function Set-Proxy {
|
|
<#
|
|
.SYNOPSIS
|
|
Sets the system proxy server and port for the current user.
|
|
|
|
.PARAMETER Server
|
|
The proxy server address (e.g., proxy.example.com).
|
|
|
|
.PARAMETER Port
|
|
The proxy server port number (e.g., 8080).
|
|
|
|
.EXAMPLE
|
|
Set-Proxy -Server proxy.example.com -Port 8080
|
|
#>
|
|
[CmdletBinding()]
|
|
[Alias('proxy')]
|
|
[OutputType([string])]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory = $true,
|
|
ValueFromPipelineByPropertyName = $true,
|
|
Position = 0)]
|
|
[string]$Server,
|
|
|
|
[Parameter(Mandatory = $true,
|
|
ValueFromPipelineByPropertyName = $true,
|
|
Position = 1)]
|
|
[int]$Port
|
|
)
|
|
|
|
# Set proxy server address and enable proxy in the user's registry
|
|
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name ProxyServer -Value "$($Server):$($Port)"
|
|
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name ProxyEnable -Value 1
|
|
|
|
# (Optional) Display the current proxy settings
|
|
# Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' | Select-Object ProxyServer, ProxyEnable
|
|
}
|
|
|
|
#endregion Proxy Configuration Function
|
|
|
|
#region File Selection Function
|
|
Function Get-File-Dialog {
|
|
<#
|
|
.SYNOPSIS
|
|
Opens a file open dialog for the user to select one or multiple files.
|
|
|
|
.PARAMETER InitialFolder
|
|
The folder that the dialog will open initially.
|
|
|
|
.OUTPUTS
|
|
String[] - Full paths of the selected files.
|
|
|
|
.EXAMPLE
|
|
$files = Get-File-Dialog -InitialFolder "E:\CodeSign\ToBeSigned"
|
|
#>
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$InitialFolder = "E:\CodeSign\ToBeSigned"
|
|
)
|
|
|
|
# Load Windows Forms assembly for GUI dialog
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
|
|
# Configure and show OpenFileDialog allowing multi-selection
|
|
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
|
InitialDirectory = $InitialFolder;
|
|
Title = "Choose file(s) to sign";
|
|
MultiSelect = $true
|
|
}
|
|
$null = $FileBrowser.ShowDialog()
|
|
|
|
# Return array of selected file paths
|
|
return $FileBrowser.FileNames
|
|
}
|
|
|
|
#endregion File Selection Function
|
|
|
|
#region File Signing Function
|
|
|
|
Function Sign-File {
|
|
<#
|
|
.SYNOPSIS
|
|
Signs one or more files using signtool.exe and moves successfully signed files.
|
|
|
|
.PARAMETER FilePath
|
|
One or more full file paths to sign. Supports pipeline input.
|
|
|
|
.PARAMETER DestinationFolder
|
|
Directory where successfully signed files will be moved.
|
|
|
|
.NOTES
|
|
Requires signtool.exe at specified path and appropriate certificates installed.
|
|
|
|
.EXAMPLE
|
|
$files | Sign-File -DestinationFolder "E:\CodeSign\SignedCode"
|
|
#>
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory = $true,
|
|
ValueFromPipeline = $true,
|
|
ValueFromPipelineByPropertyName = $true,
|
|
Position = 0)]
|
|
[string[]]$FilePath,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$DestinationFolder
|
|
)
|
|
|
|
Process {
|
|
foreach ($file in $FilePath) {
|
|
Write-Host "Signing file: $file"
|
|
|
|
# Execute signtool.exe with specified options
|
|
& "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe" sign `
|
|
/fd sha256 /td sha256 /v `
|
|
/f "E:\CodeSign\cert2025\example.cer" `
|
|
/sha1 B38EXAMPLE17340436A80B0A2FDC3BEC9352250F `
|
|
/kc CodeSignExample2025 `
|
|
/csp "Safenet Key Storage Provider" `
|
|
/tr http://timestamp.digicert.com `
|
|
$file
|
|
|
|
$exitCode = $LASTEXITCODE
|
|
|
|
if ($exitCode -eq 0) {
|
|
# Signing succeeded; ensure destination folder exists
|
|
if (-not (Test-Path -Path $DestinationFolder)) {
|
|
New-Item -Path $DestinationFolder -ItemType Directory -Force | Out-Null
|
|
}
|
|
|
|
# Move signed file to destination folder
|
|
$destinationPath = Join-Path -Path $DestinationFolder -ChildPath (Split-Path $file -Leaf)
|
|
try {
|
|
Move-Item -Path $file -Destination $destinationPath -Force
|
|
Write-Host "Moved file to $destinationPath"
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to move file $file to ${destinationPath}: $_"
|
|
}
|
|
}
|
|
else {
|
|
Write-Warning "Signing failed for $file with exit code $exitCode. File not moved."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion File Signing Function
|
|
|
|
#region Main Orchestration Function
|
|
|
|
Function Ask-Sign-Files {
|
|
<#
|
|
.SYNOPSIS
|
|
Orchestrates proxy setup, file selection, and signing of files.
|
|
|
|
.PARAMETER DestinationFolder
|
|
Optional. Destination folder for signed files. Defaults to "E:\CodeSign\SignedCode".
|
|
|
|
.PARAMETER InitialFolder
|
|
Optional. Initial folder for the file selection dialog.
|
|
|
|
.EXAMPLE
|
|
Ask-Sign-Files -InitialFolder "E:\CodeSign\ToBeSigned" -DestinationFolder "E:\CodeSign\SignedCode"
|
|
#>
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$DestinationFolder = "E:\CodeSign\SignedCode",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$InitialFolder
|
|
)
|
|
|
|
# Configure proxy settings for the user environment
|
|
Set-Proxy -Server proxy.example.com -Port 8080
|
|
|
|
# Get files to sign via file dialog
|
|
$Infiles = Get-File-Dialog -InitialFolder $InitialFolder
|
|
|
|
# Pass files and destination folder to signing function
|
|
$Infiles | Sign-File -DestinationFolder $DestinationFolder
|
|
}
|
|
|
|
#endregion Main Orchestration Function
|
|
|
|
#region Script Execution Control
|
|
|
|
# Check if script is being run directly or dot-sourced/imported
|
|
# If called directly, with more than 0 arguments
|
|
|
|
if ($args.Count -gt 0) {
|
|
# Files were dropped onto the script or shortcut, process them directly
|
|
# Assuming the DestinationFolder is set or can be defaulted
|
|
$destinationFolder = "E:\CodeSign\SignedCode"
|
|
|
|
# Validate that all args are files
|
|
$filesToSign = $args | Where-Object { Test-Path $_ -PathType Leaf }
|
|
if ($filesToSign.Count -eq 0) {
|
|
Write-Warning "No valid files passed as arguments."
|
|
exit 1
|
|
}
|
|
|
|
# Call Sign-File with the files from args
|
|
$filesToSign | Sign-File -DestinationFolder $destinationFolder
|
|
}
|
|
elseif ($MyInvocation.InvocationName.Contains($MyInvocation.MyCommand.Name) -or
|
|
$MyInvocation.InvocationName -eq $PSCommandPath) {
|
|
# Script is being run directly; invoke main function with default folders
|
|
Ask-Sign-Files -InitialFolder "E:\CodeSign\ToBeSigned" -DestinationFolder "E:\CodeSign\SignedCode"
|
|
}
|
|
|
|
#endregion Script Execution Control
|
Comments