3

I am compiling a DLL using Visual Studio 2013 and for technical reasons cannot use System.Version since it is not supported in one of my target runtime environments.

Is there a way to automatically place the assembly "FileVersion" into a constant at compile-time?

public const string MyFileVersion = "{{ PLEASE REPLACE ME }}";

I am not using a build server or anything fancy like that, just Visual Studio 2013.

Lea Hayes
  • 62,536
  • 16
  • 62
  • 111
  • You can use [#ifdev](http://msdn.microsoft.com/en-us/library/aa288458(v=vs.71).aspx) and set compile variables. – Dmitry Sevastianov Apr 09 '14 at 13:44
  • @Dmitry Can it automatically update from the assembly file version? I don't want to have maintenance hell where I forget to keep multiple versions updated... – Lea Hayes Apr 09 '14 at 13:45
  • This is a clear chicken-and-egg problem. You need an oracle that knows what the next version number needs to be. You'll have to provide one, write your own program to modify a small .cs file that contains the attribute and modify it by whatever rules you like. Run it in a prebuild event. Do keep in mind that [AssemblyFileVersion] is pretty useless, the CLR completely ignores it. It is just annotational, you see it back in the Details tab when you look at the file properties. That's all. – Hans Passant Apr 09 '14 at 14:26

1 Answers1

5

Seems like t4 templates could help you. It's template generation engine. There are enough info about it which will be helpful.

I made a simple template which does what you want. It's just an example and probably you need to make some adjustments in the code:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="Microsoft.CSharp.dll" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Reflection" #>
<#@ output extension=".cs" #>

<#
        var assemblyVersionRegex = new Regex(@"AssemblyVersion\(\""(?<version>(.*?))\""\)");
        var pathBase = new FileInfo(Host.TemplateFile).DirectoryName;
        var assemblyInfoPath = Path.Combine(pathBase, @"Properties\AssemblyInfo.cs");

        var assemblyInfoSources = File.ReadAllText(assemblyInfoPath);
        var match = assemblyVersionRegex.Match(assemblyInfoSources);
        var version = match.Success 
                ? match.Groups["version"].Value
                : "unknow";
#>

public static class SomeAssemblyInfo
{
    public const string Version = "<#= version #>";
}

So, it reads file AssemblyInfo.cs (or another if you want) get version from it and prepare class SomeAssemblyInfo :

public static class SomeAssemblyInfo
{
    public const string Version = "1.0.0.0";
}

Last thing what you need to do is run this template on build. Here you can find how to do it.

Community
  • 1
  • 1
Ivan Bianko
  • 1,749
  • 15
  • 22
  • This looks like it might be the answer, though I am getting an error: "Error 62 Compiling transformation: The name 'Host' does not exist in the current context" – Lea Hayes Apr 09 '14 at 14:26
  • @LeaHayes, have you set hostspecific="true" at the first line – Ivan Bianko Apr 09 '14 at 14:28
  • My bad, I accidentally pasted the same line twice. This works perfectly! You are a lifesaver :) – Lea Hayes Apr 09 '14 at 14:30
  • I had to change the template a little since I needed "FileVersion", but this was straightforward. – Lea Hayes Apr 09 '14 at 14:33
  • @LeaHayes yes, this is just idea, and how you get the version is up to you. You can load already compiled assembly, or make a web request. no matter – Ivan Bianko Apr 09 '14 at 14:35