Divya mohan Singh
Divya mohan Singh

Reputation: 495

How to read the assemblyversion from assemblyInfo.cs?

Hii, there are many others had already post so many question about this..But here the scenario is different.

I need to extract the first three digits ie. $(major).$(Minor).$(Build) from version number. how can i do this??..i tried AssemblyInfo Task..but that task is just for overwriting the version number.not to extract the version number.

I need to extract first three number and assign them to some property.for further use.

well,i can overwrite them using FileUpdate task.like ::

<FileUpdate 
    Files="@(AssemblyFile)" 
    Regex='(\d+)\.(\d+)\.(\d+)\.(\d+)' 
    ReplacementText='$1.$2.$3.$(Revision)'>
</FileUpdate>

now how can i use their value ie. $1,$2,$3 to assign to properties.???

Thanx.

Upvotes: 20

Views: 14255

Answers (8)

Michael Baker
Michael Baker

Reputation: 3434

If you want to be able to process your AssemblyInfo file with 100% accuracy you can use a C# task + Roslyn.

public class ReadAssemblyInfo : Task {
    [Required]
    public string AssemblyInfoFilePath { get; set; }

    [Output]
    public TaskItem AssemblyVersion { get; set; }

    [Output]
    public TaskItem AssemblyInformationalVersion { get; set; }

    [Output]
    public TaskItem AssemblyFileVersion { get; set; }

    public override bool Execute() {
        using (var reader = new StreamReader(AssemblyInfoFilePath)) {
            var text = reader.ReadToEnd();

            var tree = CSharpSyntaxTree.ParseText(text);
            var root = (CompilationUnitSyntax)tree.GetRoot();

            var attributeLists = root.DescendantNodes().OfType<AttributeListSyntax>();
            foreach (var p in attributeLists) {
                foreach (var attribute in p.Attributes) {
                    var identifier = attribute.Name as IdentifierNameSyntax;
                    
                    if (identifier != null) {
                        var value = ParseAttribute("AssemblyInformationalVersion", identifier, attribute);
                        if (value != null) {
                            SetMetadata(AssemblyInformationalVersion = new TaskItem(value.ToString()), value);
                            break;
                        }

                        value = ParseAttribute("AssemblyVersion", identifier, attribute);
                        if (value != null) {
                            SetMetadata(AssemblyVersion = new TaskItem(value.ToString()), value);
                            break;
                        }

                        value = ParseAttribute("AssemblyFileVersion", identifier, attribute);
                        if (value != null) {
                            SetMetadata(AssemblyFileVersion = new TaskItem(value.ToString()), value);
                            break;
                        }
                    }
                }
            }
        }

        return !Log.HasLoggedErrors;
    }

    private void SetMetadata(TaskItem taskItem, Version version) {
        taskItem.SetMetadata(nameof(version.Major), version.Major.ToString());
        taskItem.SetMetadata(nameof(version.Minor), version.Minor.ToString());
        taskItem.SetMetadata(nameof(version.Build), version.Build.ToString());
        taskItem.SetMetadata(nameof(version.Revision), version.Revision.ToString());
    }

    private static Version ParseAttribute(string attributeName, IdentifierNameSyntax identifier, AttributeSyntax attribute) {
        if (identifier.Identifier.Text.IndexOf(attributeName, StringComparison.Ordinal) >= 0) {
            AttributeArgumentSyntax listArgument = attribute.ArgumentList.Arguments[0];

            var rawText = listArgument.Expression.GetText().ToString();
            if (!string.IsNullOrWhiteSpace(rawText)) {
                rawText = rawText.Replace("\"", "");
                Version version;
                if (Version.TryParse(rawText, out version)) {
                    return version;
                }
            }
        }
        return null;
    }
}

Upvotes: 2

Emil G
Emil G

Reputation: 1290

Awesome thread, building upon the work of Alex and RobPol, I was able to define extended msbuild properties that is inspired by semver.org (Major, Minor, Patch, PreRelease). I chose to parse the AssemblyInformalVersion since that is the only attribute compatible with SemVer. Here is My example:

<PropertyGroup>
    <In>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs'))</In>
    <Pattern>\[assembly: AssemblyInformationalVersion\("(?&lt;Major&gt;\d+)\.(?&lt;Minor&gt;\d+)\.(?&lt;Patch&gt;[\d]+)(?&lt;PreReleaseInfo&gt;[0-9A-Za-z-.]+)?</Pattern>
    <AssemblyVersionMajor>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups["Major"].Value)</AssemblyVersionMajor>
    <AssemblyVersionMinor>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups["Minor"].Value)</AssemblyVersionMinor>
    <AssemblyVersionPatch>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups["Patch"].Value)</AssemblyVersionPatch>
    <AssemblyVersionPreRelease>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups["PreReleaseInfo"].Value)</AssemblyVersionPreRelease>
</PropertyGroup>

You can test the output of this operation by adding the following to your .csproj:

  <Target Name="AfterBuild">
    <Message Text="$(AssemblyVersionMajor)"></Message>
    <Message Text="$(AssemblyVersionMinor)"></Message>
    <Message Text="$(AssemblyVersionPatch)"></Message>
    <Message Text="$(AssemblyVersionPreRelease)"></Message>
</Target>

Ex: Snippet from my AssemblyInfo.cs:

[assembly: AssemblyInformationalVersion("0.9.1-beta")]

Will output: Major: '0', Minor: '9', Patch: '1', PreRelease: '-beta'

Upvotes: 19

Robpol86
Robpol86

Reputation: 1631

Building on Alex's answer, I used RegEx to read the AssemblyVersion (and other information) and use that in my WiX/MSI filename and version strings. Hopefully my answer isn't too noisy.

Here is the top of my .wixproj file. Points of interest are the first PropertyGroup, OutputName, and DefineConstants:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <In>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\..\MyApplication\Properties\AssemblyInfoCommon.cs'))</In>
        <Pattern>^\s*\[assembly: AssemblyVersion\(\D*(\d+)\.(\d+)\.(\d+)</Pattern>
        <AssemblyVersionMajor>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</AssemblyVersionMajor>
        <AssemblyVersionMinor>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[2].Value)</AssemblyVersionMinor>
        <AssemblyVersionBuild>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[3].Value)</AssemblyVersionBuild>
        <Pattern>^\s*\[assembly: AssemblyDescription\(\s*"([^"]+)"</Pattern>
        <AssemblyDescription>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</AssemblyDescription>
        <Pattern>^\s*\[assembly: AssemblyProduct\(\s*"([^"]+)"</Pattern>
        <AssemblyProduct>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</AssemblyProduct>
        <Pattern>^\s*\[assembly: AssemblyCompany\(\s*"([^"]+)"</Pattern>
        <AssemblyCompany>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</AssemblyCompany>
    </PropertyGroup>
    <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
        <ProductVersion>3.7</ProductVersion>
        <ProjectGuid>MYGUID00-840B-4055-8251-F2B83BC5DBB9</ProjectGuid>
        <SchemaVersion>2.0</SchemaVersion>
        <OutputName>$(AssemblyProduct)-$(AssemblyVersionMajor).$(AssemblyVersionMinor).$(AssemblyVersionBuild)</OutputName>
        <OutputType>Package</OutputType>
        <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
        <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
        <OutputPath>bin\$(Configuration)\</OutputPath>
        <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
        <DefineConstants>Debug;AssemblyVersionMajor=$(AssemblyVersionMajor);AssemblyVersionMinor=$(AssemblyVersionMinor);AssemblyVersionBuild=$(AssemblyVersionBuild);AssemblyDescription=$(AssemblyDescription);AssemblyProduct=$(AssemblyProduct);AssemblyCompany=$(AssemblyCompany)</DefineConstants>
        <SuppressValidation>False</SuppressValidation>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
        <OutputPath>bin\$(Configuration)\</OutputPath>
        <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
        <DefineConstants>AssemblyVersionMajor=$(AssemblyVersionMajor);AssemblyVersionMinor=$(AssemblyVersionMinor);AssemblyVersionBuild=$(AssemblyVersionBuild);AssemblyDescription=$(AssemblyDescription);AssemblyProduct=$(AssemblyProduct);AssemblyCompany=$(AssemblyCompany)</DefineConstants>
    </PropertyGroup>

And then in a .wxi file I have this:

<?define MajorVersion="$(var.AssemblyVersionMajor)" ?>
<?define MinorVersion="$(var.AssemblyVersionMinor)" ?>
<?define BuildVersion="$(var.AssemblyVersionBuild)" ?>
<?define VersionNumber="$(var.MajorVersion).$(var.MinorVersion).$(var.BuildVersion)" ?>

And finally in my Product.wxs:

<?include Definitions.wxi ?>
<Product Id="$(var.GuidProduct)" Name="$(var.AssemblyProduct) $(var.VersionNumber)" Language="!(loc.LANG)"
         Version="$(var.VersionNumber)" Manufacturer="$(var.AssemblyCompany)" UpgradeCode="$(var.GuidUpgrade)">
    <Package Id="$(var.GuidPackage)" InstallerVersion="301" Compressed="yes" InstallScope="perMachine"
             Keywords="!(loc.Keywords)" Description="$(var.AssemblyProduct)" Comments="$(var.AssemblyDescription)" />

Upvotes: 11

Alex Isayenko
Alex Isayenko

Reputation: 679

You can read lines from files, get the string using regex and change it if you need. And if you're using MSBuild 4.0 you can use Property Functions, which give you an access to .NET API. This example should give you first three numbers of the AssemblyVersion.

<Target Name="ReadAssemblyVersion">

    <ReadLinesFromFile File="$(VersionFile)">
        <Output TaskParameter="Lines"
                ItemName="ItemsFromFile"/>
    </ReadLinesFromFile>

    <PropertyGroup>
        <Pattern>\[assembly: AssemblyVersion\(.(\d+)\.(\d+)\.(\d+)</Pattern>
        <In>@(ItemsFromFile)</In>
        <Out>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern)))</Out>
    </PropertyGroup>

    <Message Text="Output : $(Out.Remove(0, 28))"/>

</Target>

http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx

Upvotes: 33

lanoxx
lanoxx

Reputation: 13061

I just found this on google, might help:

http://msdn.microsoft.com/en-us/library/system.reflection.assemblyname.version%28v=VS.90%29.aspx

Particularly:

//For AssemblyFileVersion
Assembly asm = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);
string version = fvi.FileVersion
//For AssemblyVersion
string revision = Assembly.GetExecutingAssembly().GetName().Version.Revision;

Upvotes: 1

Bart Janson
Bart Janson

Reputation: 233

I use the RegexMatch-task from the MSBuild.Community.Tasks.

You can write the output of the match to an itemgroup, although you want to read it into 3 properties, as above, a custom task would then be prefered.

Upvotes: 0

Filburt
Filburt

Reputation: 18082

You can use MSBuild.Community.Tasks.AssemblyInfo.AssemblyVersion to access AssemblyVersion and AssemblyFileVersion from AssemblyInfo.cs.

Indeed this task can only be used to set the version.

Maybe this post is usefull.

Upvotes: 0

Gerrie Schenck
Gerrie Schenck

Reputation: 22368

The only solution is to write a custom build task, and parse the version number manually in the code.

Upvotes: -3

Related Questions