Finally! For anyone else trying to do the same, here are the steps, assuming that you're using shared AssemblyInfo that resides in solution directory (it can work for default AssemblyInfo too, but you'll need to adjust paths and filenames accordingly):
- Download and install MSBuild Community Tasks on your machine.
- Add a targets file (a simple XML file with
.targets
extension) to your project.
- Add
UsingTask
presented in Kent Boogaart's article I linked in the question to this file. This will perform actual version writing on the splash image.
- Use
<Version>
, <FileUpdate>
and <AddTextToImage>
tasks (first two are available in MSBuild, third one is from the UsingTask
we added in step 3) to write new version number to your shared AssemblyInfo file and splash image.
The final .targets
file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="AddTextToImage" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<InputPath ParameterType="System.String" Required="true" />
<OutputPath ParameterType="System.String" Required="true" />
<TopMiddlePoint ParameterType="System.String" Required="true" />
<Text1 ParameterType="System.String" Required="true" />
<Text2 ParameterType="System.String" Required="false" />
<Text3 ParameterType="System.String" Required="false" />
</ParameterGroup>
<Task>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Xaml" />
<Using Namespace="System" />
<Using Namespace="System.Globalization" />
<Using Namespace="System.IO" />
<Using Namespace="System.Windows" />
<Using Namespace="System.Windows.Media" />
<Using Namespace="System.Windows.Media.Imaging" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var originalImageSource = BitmapFrame.Create(new Uri(InputPath));
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
{
drawingContext.DrawImage(originalImageSource, new Rect(0, 0, originalImageSource.PixelWidth, originalImageSource.PixelHeight));
var typeFace = new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Bold, FontStretches.Normal);
var formattedText = new FormattedText(Text1, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeFace, 18, Brushes.Red);
var topMiddlePoint = Point.Parse(TopMiddlePoint);
var point = new Point(topMiddlePoint.X - (formattedText.Width / 2), topMiddlePoint.Y);
drawingContext.DrawText(formattedText, point);
if(!string.IsNullOrEmpty(Text2))
{
formattedText = new FormattedText(Text2, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeFace, 18, Brushes.Red);
topMiddlePoint.Y += formattedText.Height + 5;
point = new Point(topMiddlePoint.X - (formattedText.Width / 2), topMiddlePoint.Y);
drawingContext.DrawText(formattedText, point);
}
if(!string.IsNullOrEmpty(Text3))
{
formattedText = new FormattedText(Text3, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeFace, 18, Brushes.Red);
topMiddlePoint.Y += formattedText.Height + 5;
point = new Point(topMiddlePoint.X - (formattedText.Width / 2), topMiddlePoint.Y);
drawingContext.DrawText(formattedText, point);
}
drawingContext.Close();
}
var renderTargetBitmap = new RenderTargetBitmap(originalImageSource.PixelWidth, originalImageSource.PixelHeight, originalImageSource.DpiX, originalImageSource.DpiY, PixelFormats.Pbgra32);
renderTargetBitmap.Render(visual);
var bitmapFrame = BitmapFrame.Create(renderTargetBitmap);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(bitmapFrame);
using (var stream = File.OpenWrite(OutputPath))
{
encoder.Save(stream);
stream.Close();
}
]]>
</Code>
</Task>
</UsingTask>
<PropertyGroup>
<MajorVersion>2</MajorVersion>
<MinorVersion>5</MinorVersion>
</PropertyGroup>
<Target Name="BeforeBuild">
<Version BuildType="Automatic" RevisionType="Automatic" Major="$(MajorVersion)" Minor="$(MinorVersion)">
<Output TaskParameter="Major" PropertyName="Major" />
<Output TaskParameter="Minor" PropertyName="Minor" />
<Output TaskParameter="Build" PropertyName="Build" />
<Output TaskParameter="Revision" PropertyName="Revision" />
</Version>
<FileUpdate Files="$(SolutionDir)SharedAssemblyInfo.vb"
Regex="Assembly: AssemblyVersion\("\d+\.\d+((\.\*)|(\.\d+\.\d+))?"\)"
ReplacementText="Assembly: AssemblyVersion("$(Major).$(Minor).$(Build).$(Revision)")" />
<FileUpdate Files="$(SolutionDir)SharedAssemblyInfo.vb"
Regex="Assembly: AssemblyFileVersion\("\d+\.\d+((\.\*)|(\.\d+\.\d+))?"\)"
ReplacementText="Assembly: AssemblyFileVersion("$(Major).$(Minor).$(Build).$(Revision)")" />
<SvnVersion LocalPath=".">
<Output TaskParameter="Revision" PropertyName="SvnRevision" />
</SvnVersion>
<AddTextToImage InputPath="$(ProjectDir)Resources\Splash.png"
OutputPath="$(ProjectDir)Resources\SplashWithVersion.png"
TopMiddlePoint="250,150"
Text1="$(Major).$(Minor).$(Build).$(Revision)"
Text2="SVN Version: $(SvnRevision)" />
<Message Text="Updated version number on splash screen to: $(Major).$(Minor).$(Build).$(Revision)" Importance="high"/>
</Target>
</Project>
This will update your AssemblyInfo and the output image. Note that you must mark your output image as SplashScreen
(as Build Action) in Visual Studio. Also note that I'm writing both assembly version as well as SVN Revision number on the splash screen. You may want to adjust yours according to your needs.