The trick was to match the so-called assembly identity.
Hint #1: do not use Mage to generate the deployment manifest (the *.application file). Use GenerateDeploymentManifest
instead. The Mage tool lacks two crucial options:
- Mage provides no way to specify the culture of the deployment. As you can see from the link above, if the culture doesn't match then to ClickOnce it's a different application. Ouch.
- It's not possible to set the update mode to "foreground", aka "check updates before starting", aka "online application". Hmm...
Hint #2: DO use Mage to add publisher and sign the deployment certificate. This is because GenerateDeploymentManifest
seems to ignore Publisher (in 3.5 SP1 at least), and similarly SignFile
is unable to use a .pfx file as the key. Whoops.
<Exec Command='"c:\path\to\mage.exe" -Update "$(MyOutputPath)\MyApp.application" -Publisher MyCompany.com -CertFile path\to\MyAppKey.pfx'/>
Hint #3: to supply the correct relative path for the "codebase" field in the deployment XML, use the following snippet:
<CreateItem Include="$(MyDeploymentPath)\v$(Version)\MyApp.exe.manifest" AdditionalMetadata="TargetPath=v$(Version)\MyApp.exe.manifest">
<Output TaskParameter="Include" ItemName="EntryPoint"/>
</CreateItem>
and then pass EntryPoint="@(EntryPoint)"
to GenerateDeploymentManifest
. The key bit is the "TargetPath" metadata. Yuck!
Hint #4: patience, a supply of old working manifests, and a good comfy diff tool.
Is this complicated and painful? Yes! But is it better than the Publish wizard? OH YES!
Edit: I've posted a working example of how one might invoke Mage from MSBuild - however working doesn't mean you can just plug it in, since there are lots of settings involved that you may want to change, and you still need to understand ClickOnce to some extent. But hopefully it can provide a useful starting point.