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.

Task Scheduler: Directory not found (Error Value: 2147942403)

Just a brief post to help people stuck with thi sin the future. Today, when starting a Task Scheduler job, we got the following error:

Task Scheduler failed to start instance "{SOME GUID}" of "My Task name" task for user "MyDomain\MyUser" . Additional Data: Error Value: 2147942403.

After some searching, this turned out to be a problem with the action we tried to run in the task. It was set to an exe file, but in a non-existing directory. Correcting the directory fixed the problem:

1. Go to the task Properties
2. Go to tab Actions
3. Look for an action that uses a path
4. Double click it, and correct the path to a correct path

Sitecore PDF indexing errors

Some time ago, we noticed our Sitecore 8.0 install was showing errors in our production Crawling logs similar to this:

ManagedPoolThread #16 08:02:41 ERROR Could not compute value for ComputedIndexField: _content for indexable: sitecore://web/{8767E7A4-171A-478B-B421-ACF46B60D4F1}?lang=en&ver=1
Exception: System.Runtime.InteropServices.COMException

Using Ryan Bailey’s blog, we found this was a problem with indexing the PDFs in our media library. Apparently, Sitecore’s Lucene crawler defaults to indexing PDFs, but cannot extract the contents of the PDFs on its own.

In general, there are two solutions to this problem: Allow Sitecore to index PDFs, or remove PDFs from the indexing. To enable indexing, have a look at this post by John West and this Stack Overflow answer. The solution involves adding a series of DLLs to your Sitecore installation, which extract the PDF contents for processing by Lucene. You could also have a look at these two posts by Ryan Bailey.

We, however, opted to exclude PDF indexing for now, as Lucene was not (yet) used by our site visitors. To do this, remove the mimetype application/pdf from the list of indexed mimetypes:


<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<indexConfigurations>
<defaultLuceneIndexConfiguration>
<mediaIndexing>
<mimeTypes>
<includes>
<mimeType>
<patch:delete>
application/pdf
</patch:delete>
</mimeType>
</includes>
</mimeTypes>
</mediaIndexing>
</defaultLuceneIndexConfiguration>
</indexConfigurations>
</contentSearch>
</sitecore>
</configuration>

Personal note: As I’ll be switching companies next month, fewer posts may be about Sitecore and more about .NET development in general. But not to worry, Sitecore is certainly not out of the picture!

Installing a Sitecore language pack

Just a quick blog post: I regularly have to reinstall a language pack in Sitecore, but often can’t find the official instructions from Sitecore.

Language packs are dependent on your Sitecore version, but not all Sitecore versions have a new version of a language pack. The Sitecore version-independent instructions can be found at Sitecore Experience Platform Client Translations Manual. This page has a warning about installing newer language packs in newer Sitecore versions, but not vice versa!

For example, the newest Dutch language pack was published with Sitecore 8.0-update 4. When installing Sitecore 8.1-update 3, we’ll use this language pack.

SitecoreLinked: Undocumented but useful!

Glass.Mapper is a very type-safe way of programming in Sitecore using templates. Among other things, it allows you to map the fields of an item to the properties of an object.

One of the undocumented features is the SitecoreLinked attribute. It is only given stage time at one of the Glass tutorials, without further explanation. It allows you to map a list of linked items to an IEnumerable, like the Navigate > Links Sitecore Ribbon button does.

Sometimes, you don’t want all linked items, but only incoming or outgoing links. For this, add Option = SitecoreLinkedOptions.References or Option = SitecoreLinkedOptions.Referrers to the SitecoreLinked attribute.


[SitecoreType(TemplateId = "D3F78276-354C-4265-AE29-BBEC0EFEF04F")]
public class MainItem
{
[SitecoreLinked(InferType=true)]
public virtual IEnumerable AllLinkedItemsAsList { get; set; }

[SitecoreLinked(InferType=true, Option = SitecoreLinkedOptions.Referrers)]
public virtual IEnumerable IncomingLinkedItemsAsList { get; set; }

}

To just get a list of all items linked in a particular field, you don’t need the SitecoreLinked attribute, only a SitecoreField attribute:


[SitecoreType(TemplateId = "D3F78276-354C-4265-AE29-BBEC0EFEF04F")]
public class MainItem
{
[SitecoreField(FieldId = "168CBC07-46F8-4EA2-9E35-855493720DEA")]
public virtual IEnumerable RelatedItemsAsList { get; set; }
}

[SitecoreType(TemplateId = "AE63A28F-9D86-4752-9F09-6B094062EB6B")]
public class Related
{
}

(Slightly) more info to be found at:

Translating Sitecore PowerShell Extensions

Sitecore Powershell Extensions is a great way of changing a lot of items in bulk, giving your content editors a lot of power. Unfortunately, the tool is only available in English, confusing people using non-English sites by inserting blank titles in the Start Menu and Content Editor context menu.

Non-translated Start Menu
Well, that’s not very helpful…

 

This isn’t difficult to fix, though. Translate the following items to your language of choice:

  • All four applications under:
    • core:/sitecore/content/Applications/PowerShell/PowerShellIse
    • core:/sitecore/content/Applications/PowerShell/PowerShellListView
    • core:/sitecore/content/Applications/PowerShell/PowerShell Console
    • core:/sitecore/content/Applications/PowerShell/PowerShell Runner
  • All Ribbons, buttons and menus under::
    • core:/sitecore/content/Applications/PowerShell/PowerShellIse
    • core:/sitecore/content/Applications/PowerShell/PowerShellListView
  • The three items in the content editor context menu:
    • core:/sitecore/content/Applications/Content Editor/Context Menues/Default/Edit Script
    • core:/sitecore/content/Applications/Content Editor/Context Menues/Default/PowerShell Console
    • core:/sitecore/content/Applications/Content Editor/Context Menues/Default/Context PowerShell Scripts
  • The five items in the Start Menu:
    • core:/sitecore/content/Documents and settings/All users/Start menu/Right/PowerShell Console
    • core:/sitecore/content/Documents and settings/All users/Start menu/Right/PowerShell Toolbox
    • core:/sitecore/content/Documents and settings/All users/Start menu/Right/Development Tools/PowerShell ISE
    • core:/sitecore/content/Documents and settings/All users/Start menu/Right/Reporting Tools/PowerShell Reports
    • core:/sitecore/content/Documents and settings/All users/Start menu/Right/Reporting Tools/PowerShell Reports/PowerShell Fake Report
  • The Launch Pad button at:
    • core:/sitecore/client/Applications/Launchpad/PageSettings/Buttons/ContentEditing/PowerShell ISE

Fill the Text, Display Name and/or Tooltip properties, depending on the English language version.

Non-translated item
Just add a new version in your language

Using these guidelines, some translations are done twice. For example, the application PowerShell ISE and the Start Menu item PowerShell ISE. Can’t hurt to be thorough, though.

Also, be sure to translate the fonts at master:/sitecore/system/Modules/PowerShell/Fonts, or your ISE will show in font Monaco.

Good luck!

(Edit July 21, 2016: Added several items to translated)

Hello world!

After procrastinating about it for far too long, I finally bit the bullet and started a blog. I’m going to write about software craftsmanship, daily problems I encounter in development and interesting developments in software development and -architecture.

For now, I want to do a blog post about the Sitecore architecture I’m currently setting up. Sitecore is a versatile product, and quite feature-complete, but I’ve had difficulty defining an architecture for a Sitecore enterprise application. My team and I want to do Test-Driven Development (TDD), and integrate both a customer portal and a public-facing site into Sitecore. Having done a lot of searching, I soon intend to document our findings!