ClickOnce and Git: Different computed hash than specified in manifest

ClickOnce. While the concept is great, the execution is not fantastic. Try creating a separate version, downloadable from your testing URL. But that’s a story for another day.

ClickOnce allows continuous updates delivered to your clients, something any Windows client developer would like. However, after distributing your application, many developers are plagued with an error about a file or the applicatoin having a “different computed hash than specified in manifest”.

TL; DR: Merging branches with Git changes something about the files. As specified in this SO answer, add a .gitattributes file with these lines:
*.vsto binary
*.deploy binary
*.manifest binary

ClickOnce computes hashes over all files, and any .exe or .dll files are appended with a .deploy extension. The .manifest file lists all SHA1 hashes for all files, you can check these using this code:


using System;
using System.Security.Cryptography;
using System.IO;

namespace FileHashSample
{
public class FileHash
{
public FileHash()
{
return;
}

public string ComputeHash(string filePath)
{
string filePathNormalized = System.IO.Path.GetFullPath(filePath);
SHA1 sha = new SHA1Managed();
FileStream fs = new FileStream(filePathNormalized, FileMode.Open, FileAccess.Read);
byte[] byteHash = sha.ComputeHash(fs);
fs.Close();
return Convert.ToBase64String(byteHash, 0, byteHash.Length);
}

public static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Please Enter a File Path");
return;
}
string filePath = System.IO.Path.GetFullPath(args[0]);
FileHash objFileHash = new FileHash();
Console.WriteLine("File Path is {0}", filePath);
Console.WriteLine("File Hash is {0}", objFileHash.ComputeHash(filePath));
return;
}
}

}

(From this MSDN question)

Finally, this .manifest file is hashed and the hash is noted in your .application file. If any of these files changes, the hashes need to be recomputed using Mage.exe and Mageui.exe. And alas, merging Git branches sometimes changes the .manifest file slightly, resulting in a different hash. However, as you didn’t update the hash for the .manifest file in the .application file, installation fails with an error about a “different computed hash than specified in manifest”. The solution? Tell Git not to change the .manifest file, using this SO answer: Add a .gitattributes file containing the following lines:


*.vsto binary
*.deploy binary
*.manifest binary

If, after doing this, your application is still complaining about a different hash on a .config file, don’t mark that as binary as well: You might like to diff these! Instead, consider disabling hashing for .config files: In Visual Studio, open Properties, go to Publish and click Application Files. On the screen that appears, you can disable hashing in the last column. However, for DLLs, I’d recommend keeping these hashes, disabling it for just one config file should be acceptable.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.