Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

How can one read the AssemblyFileVersion, or its components AssemblyFileMajorVersion, AssemblyFileMinorVersion, AssemblyFileBuildNumber, AssemblyFileRevision, within the .csproj, following compilation?

I have tried the following which pulls the information from the built assembly:

<Target Name="AfterCompile">
    <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
         <Output
             TaskParameter="Assemblies"
             ItemName="MyAssemblyIdentities"/>
    </GetAssemblyIdentity>
    <Message Text="AssemblyVersion = %(MyAssemblyIdentities.Version)" />
</Target>

But that retrieves the AssemblyVersion and not the AssemblyFileVersion. There does not seem to be a documented metadata entry for the latter. I also tried:

<Import Project="$(MSBuildExtensionsPath)ExtensionPackMSBuild.ExtensionPack.tasks" />
<Target Name="AfterCompile">
    <MSBuild.ExtensionPack.Framework.Assembly TaskAction="GetInfo" NetAssembly="$(TargetPath)">
        <Output TaskParameter="OutputItems" ItemName="Info" />
    </MSBuild.ExtensionPack.Framework.Assembly>
    <Message Text="AssemblyFileVersion = %(Info.FileVersion)" />
</Target>

Unfortunately, while this retrieves the correct value, it also file locks the assembly until VS2008 is closed.

Frankly, neither is what I want as I would rather read the information from the AssemblyInfo.cs directly. However, I cannot figure out how to do that. I assumed AssemblyInfo in the MSBuild Extensions was one way, but it seems focused on writing to the AssemblyInfo and not retrieving values from it.

How can I best accomplish this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
301 views
Welcome To Ask or Share your Answers For Others

1 Answer

I've managed to solve this using a custom task. The class library DLL is as so (some code adjusted/eliminated for brevity):

using System;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;

namespace GetAssemblyFileVersion
{
    public class GetAssemblyFileVersion : ITask
    {
        [Required]
        public string strFilePathAssemblyInfo { get; set; }
        [Output]
        public string strAssemblyFileVersion { get; set; }
        public bool Execute()
        {
            StreamReader streamreaderAssemblyInfo = null;
            Match matchVersion;
            Group groupVersion;
            string strLine;
            strAssemblyFileVersion = String.Empty;
            try
            {
                streamreaderAssemblyInfo = new StreamReader(strFilePathAssemblyInfo);
                while ((strLine = streamreaderAssemblyInfo.ReadLine()) != null)
                {
                    matchVersion = Regex.Match(strLine, @"(?:AssemblyFileVersion("")(?<ver>(d*).(d*)(.(d*)(.(d*))?)?)(?:""))", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                    if (matchVersion.Success)
                    {
                        groupVersion = matchVersion.Groups["ver"];
                        if ((groupVersion.Success) && (!String.IsNullOrEmpty(groupVersion.Value)))
                        {
                            strAssemblyFileVersion = groupVersion.Value;
                            break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                BuildMessageEventArgs args = new BuildMessageEventArgs(e.Message, string.Empty, "GetAssemblyFileVersion", MessageImportance.High);
                BuildEngine.LogMessageEvent(args);
            }
            finally { if (streamreaderAssemblyInfo != null) streamreaderAssemblyInfo.Close(); } 
            return (true);
        }
        public IBuildEngine BuildEngine { get; set; }
        public ITaskHost HostObject { get; set; }
    }
}

And in the project file:

<UsingTask AssemblyFile="GetAssemblyFileVersion.dll" TaskName="GetAssemblyFileVersion.GetAssemblyFileVersion" />
<Target Name="AfterCompile">
    <GetAssemblyFileVersion strFilePathAssemblyInfo="$(SolutionDir)AssemblyInfo.cs">
        <Output TaskParameter="strAssemblyFileVersion" PropertyName="strAssemblyFileVersion" />
    </GetAssemblyFileVersion>
    <Message Text="AssemblyFileVersion = $(strAssemblyFileVersion)" />
</Target>

I've tested this and it will read the updated version if you use MSBuild.ExtensionPack.VersionNumber.targets for auto-versioning.

Obviously, this could be easily extended so that a regex is passed from the project file to a more general-purpose custom task in order to obtain any match in any file.


Update 2009/09/03:

One additional change has to be made to make the ApplicationVersion update on each build. InitialTargets="AfterCompile" must be added to the <Project.... This was solved by Chao Kuo.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...