How to read the assemblyversion from assemblyInfo.

2020-02-08 06:55发布

问题:

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.

回答1:

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



回答2:

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



回答3:

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'



回答4:

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)" />


回答5:

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;


回答6:

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;
    }
}


回答7:

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.



回答8:

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.