views:

387

answers:

4

Let's say I wanted to create a static text file which ships with each release. I want the file to be updated with the version number of the release (as specified in AssemblyInfo.cs), but I don't want to have to do this manually.

I was hoping I could use a post-build event and feed the version number to a batch file like this:

call foo.bat $(AssemblyVersion)

However I can't find any suitable variable or macro to use.

Is there any way to achieve this that I've missed?

A: 

I think the best thing you can do is look at MSBuild and MsBuild Extension Pack you should be able to edit you solution file so that a post build event occurs and writes to your test file.

If this is too complicated then you could simply create a small program that inspects all assemblies in you output directory and execute it on post build, you could pass in the output directory using the variable name... for example in the post build event...

AssemblyInspector.exe "$(TargetPath)"

class Program
{
    static void Main(string[] args)
    {
        var assemblyFilename = args.FirstOrDefault();
        if(assemblyFilename != null && File.Exists(assemblyFilename))
        {
            try
            {
                var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFilename);
                var name = assembly.GetName();

                using(var file = File.AppendText("C:\\AssemblyInfo.txt"))
                {
                    file.WriteLine("{0} - {1}", name.FullName, name.Version);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}

You could also pass in the text file location...

Rohan West
+1  A: 

As a workaround I've written a managed console application which takes the target as a parameter, and returns the version number.

I'm still interested to hear a simpler solution - but I'm posting this in case anyone else finds it useful.

using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;

namespace Version
{
    class GetVersion
    {
        static void Main(string[] args)
        {
            if (args.Length == 0 || args.Length > 1) ShowUsage();

            string target = args[0];

            string path = Path.IsPathRooted(target) 
                                ? target 
                                : Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + Path.DirectorySeparatorChar + target;

            Console.Write( Assembly.LoadFile(path).GetName().Version.ToString(2) );
        }

        static void ShowUsage()
        {
            Console.WriteLine("Usage: version.exe <target>");
        }
    }
}
Winston Smith
+2  A: 

If you prefer scripting these methods might also work for you:

If you are using the post-build event, you can use the filever.exe tool to grab it out of the already built assembly:

for /F "tokens=4" %%F in ('filever.exe /B /A /D bin\debug\myapp.exe') do (
  set VERSION=%%F
)
echo The version is %VERSION%

Get filever.exe from here: http://support.microsoft.com/kb/913111

If you are using the pre-build event, you can take it out of the AssemblyInfo.cs file as follows:

set ASMINFO=Properties\AssemblyInfo.cs
FINDSTR /C:"[assembly: AssemblyVersion(" %ASMINFO% | sed.exe "s/\[assembly: AssemblyVersion(\"/SET CURRENT_VERSION=/g;s/\")\]//g;s/\.\*//g" >SetCurrVer.cmd
CALL SetCurrVer.cmd
DEL SetCurrVer.cmd
echo Current version is %CURRENT_VERSION%

This uses the unix command line tool sed, which you can download from many places, such as here: http://unxutils.sourceforge.net/ - iirc that one works ok.

A: 

I've started adding a separate project that builds last and adding a post build event to that project that runs itself. Then I just perform my post build steps programmatically in there.

Makes it a lot easier to do stuff like this. Then you can just inspect the assembly attributes of whatever assembly you want. So far its working pretty awesome.

Joshua Evensen