Simple scenario. Visual studio generates and signs things as part of the publish process.
I then go to the MyApp.dll.config.deploy
file and update some settings.
Now when I try to install the application the clickonce installer says the MyApp.dll.config
has a different computed hash than specified in manifest.
So I tried mage.exe -sign MyApplicationManifest -certfile ... -password ...
which results in MyApp.vsto successfully signed
But I still receive the computed hash error. Am I missing a step?
I've read the following links: http://msdn.microsoft.com/en-us/library/acz3y3te(v=vs.110).aspx http://blogs.msdn.com/b/msiclickonce/archive/2009/07/17/clickonce-application-fails-after-changing-configuration-file-and-resigning-the-manifest.aspx
There's a few steps that need to happen to resign the manifests. I used powershell to do it automatically.
.deploy
extension you'll need to rename them back to the original.mage.exe -update
on your application manifest. If you have a deployment manifest you'll need to do the same, except in the command line argument to mage.exe you need to specify the relative location to the application manifest.delcert.exe
and then sign it using signtool.exe
Note: Once an exe has been signed it cannot be resigned with signtool unless you remove the signing with delcert.exe.
If your clickonce is a VSTO clickonce your manifest names will be different (I think MyApp.dll.manifest vs MyApp.exe.manifest).
Update I've included the powershell script with sensitive information redacted.
$root = "$PSScriptRoot"
$ToolsPath = "C:\Tools"
$CertFile = $ToolsPath + "\REMOVED"
$CertPassword = "REMOVED"
#Update the setup.exe bootstrappers update url
Start-Process "$PSScriptRoot\setup.exe" -ArgumentList "-url=`"$ClickOnceUpdateUrl`"" -Wait
#The bootstrappers signature is now invalid since we updated the url
#We need to remove the old signature
Start-Process 'C:\Tools\delcert.exe' -ArgumentList "`"$root\setup.exe`"" -Wait
Write-Host "$root [writeline]"
#Resign with signtool
Invoke-Expression 'C:\Tools\signtool.exe sign /d "PUBLISHER NAME" /f "$CertFile" /p "$CertPassword" "$root\setup.exe"'
#update config properties
$CodeBasePath = Convert-Path "$PSScriptRoot\Application Files\MYAPP_*"
$ConfigPath = $CodeBasePath + "\MYAPP.dll.config.deploy"
[xml] $xml = Get-Content $ConfigPath
$ApiEndpoint = $xml.SelectSingleNode('/configuration/appSettings/add[@key="MYAPP:ApiBaseUrl"]')
$ApiEndpoint.value = $MYAPPApiEndpoint
$xml.Save($ConfigPath)
#Begin Resigning various Manifests
$AppManifestPath = Convert-Path "Application Files\MYAPP_*\MYAPP.dll.manifest"
#Need to resign the application manifest, but before we do we need to rename all the files back to their original names (remove .deploy)
Get-ChildItem "$CodeBasePath\*.deploy" -Recurse | Rename-Item -NewName { $_.Name -replace '\.deploy','' }
#Resign application manifest
Invoke-Expression 'C:\Tools\mage.exe -update "$CodeBasePath\MYAPP.dll.manifest" -certFile "$CertFile" -password "$CertPassword" -if "ID.ico"'
#Regisn deployment manifests in root and versioned folder
Invoke-Expression 'C:\Tools\mage.exe -update "$CodeBasePath\MYAPP.vsto" -certFile "$CertFile" -password "$CertPassword" -appManifest "$AppManifestPath" -pub "PUBLISHER NAME" -ti "http://timestamp.globalsign.com/scripts/timstamp.dll"'
Invoke-Expression 'C:\Tools\mage.exe -update "$root\MYAPP.vsto" -certFile "$CertFile" -password "$CertPassword" -appManifest "$AppManifestPath" -pub "PUBLISHER NAME" -ti "http://timestamp.globalsign.com/scripts/timstamp.dll"'
#Rename files back to the .deploy extension, skipping the files that shouldn't be renamed
Get-ChildItem -Path "Application Files\*" -Recurse | Where-Object {!$_.PSIsContainer -and $_.Name -notlike "*.manifest" -and $_.Name -notlike "*.vsto"} | Rename-Item -NewName {$_.Name + ".deploy"}