3 May 2012

MSBuild Task to generate hash of files

Here's a handy inline MSBuild task to take a bunch of files and generate a hash. I used it to generate a hash of source files in order to determine if an exe has really been changed (given that exe's compile to distinct files each time even if the source hasn't changed).

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<UsingTask TaskName="GenerateHash" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<InputFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<OutputFile ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO" />
<Using Namespace="System.Linq" />
<Using Namespace="System.Security.Cryptography" />
<Code Type="Fragment" Language="cs"><![CDATA[
using (var ms = new MemoryStream())
using (var md5 = MD5.Create())
{
foreach (var item in InputFiles)
{
string path = item.ItemSpec;
using (FileStream stream = new FileStream(path, FileMode.Open))
{
var fileHash = md5.ComputeHash(stream);
ms.Write(fileHash, 0, fileHash.Length);
}
}
ms.Flush();
ms.Position = 0;
var dirHash = md5.ComputeHash(ms);
using (TextWriter w = new StreamWriter(OutputFile, false))
{
w.WriteLine(string.Join("", dirHash.Select(b => b.ToString("x2"))));
}
}
]]></Code>
</Task>
</UsingTask>

<Target Name="Demo">
<GenerateHash InputFiles="@(SomeFiles)" OutputFile="res.txt" />
</Target>
</Project>

No comments: