Skip to content

Instantly share code, notes, and snippets.

@dwilliamsuk
Created February 10, 2026 08:23
Show Gist options
  • Select an option

  • Save dwilliamsuk/3da97cd05dac680fa47edfb02bf2aec7 to your computer and use it in GitHub Desktop.

Select an option

Save dwilliamsuk/3da97cd05dac680fa47edfb02bf2aec7 to your computer and use it in GitHub Desktop.
PowerShell script to add the certificate of a ClickOnce app publisher to the "Trusted Publisher" certificate store for the current user. This allows ClickOnce apps to launch without prompting the user for trust. Requires the ClickOnce app to be signed with a certificate.
<#
.SYNOPSIS
This script trusts a ClickOnce app publisher for a user.
.DESCRIPTION
This script adds the certificate of a ClickOnce app publisher to the "Trusted Publisher"
certificate store for the current user. This allows ClickOnce apps to launch without
prompting the user for trust.
.PARAMETER ApplicationManifestURL
This is the URL of the ClickOnce application manifest file you want to trust.
- Type: [Uri]
- Mandatory: True
.EXAMPLE
An example of running this script is shown below.
PS C:\> .\Trust-ClickOnce.ps1 -ApplicationManifestURL "https://example.com/ExampleApp.application"
.NOTES
Author: github.com/dwilliamsuk
Date: 14/10/2025
Version: 1.0
Script Purpose: Trusts a ClickOnce app publisher for a user.
Dependencies: N/A
#>
function Get-ClickOnce-Publisher-x509 {
param (
[Uri]$ManifestURL
)
$web_request_object = Invoke-WebRequest -UseBasicParsing -Method "GET" -Uri $ManifestURL
if ( ($web_request_object) -and ($web_request_object.StatusCode -eq 200) ) {
# Store response in variable as XML object
$application_manifest = [xml]::new()
$application_manifest.Load($web_request_object.RawContentStream)
# Get x509 signing certs in manifest
$application_manifest_x509_subject = $application_manifest.assembly.Signature.KeyInfo.RelData.license.grant.AuthenticodePublisher.X509SubjectName
$application_manifest_x509_data = $application_manifest.assembly.Signature.KeyInfo.RelData.license.issuer.Signature.KeyInfo.X509Data
# For each x509 cert, find the cert of the publisher and add to trusted publisher store.
# This loop doesn't add the rest of the CA chain, as Windows will grab CA certs at
# runtime via Windows Update.
foreach ($x509_certificate in $application_manifest_x509_data.X509Certificate) {
$decoded_x509_certificate = [Convert]::FromBase64String($x509_certificate)
$certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($decoded_x509_certificate)
# Match for app cert (the only one we want to trust)
if ($certificate.Subject -eq $application_manifest_x509_subject) {
return $certificate
} else {
$certificate.Dispose()
}
}
throw "Unable to find publisher x509 cert!"
} else {throw "Web request failed!"}
}
function Trust-Publisher-X509 {
param (
[System.Security.Cryptography.X509Certificates.X509Certificate2]$X509Cert
)
$CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "TrustedPublisher", "CurrentUser"
$CertStore.Open('ReadWrite')
$CertStore.Add($X509Cert)
$CertStore.Close()
return
}
$ApplicationManifestURL = $args[0]
$PublisherCert = Get-ClickOnce-Publisher-x509 -ManifestURL $ApplicationManifestURL
Write-Output "Found certificate! $($PublisherCert.DnsNameList.Unicode) [$($PublisherCert.Thumbprint)]"
Trust-Publisher-X509 -X509Cert $PublisherCert
Write-Output "Trusted certificate!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment