【问题标题】:How to read the assemblyversion from assemblyInfo.cs?如何从 assemblyInfo.cs 中读取 assemblyversion?
【发布时间】:2011-01-03 18:46:33
【问题描述】:

嗨, 有很多其他人已经发布了很多关于这个的问题..但是这里的情况不同。

我需要提取前三个数字,即。 $(major).$(Minor).$(Build) 来自版本号。 我该怎么做??..我试过AssemblyInfoTask..但该任务只是为了覆盖版本号。不是提取版本号。

我需要提取前三个数字并将它们分配给某个属性。以供进一步使用。

好吧,我可以使用FileUpdate task.like ::

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

现在我该如何使用它们的价值,即。 $1,$2,$3 分配给属性。???

谢谢。

【问题讨论】:

    标签: msbuild installation windows-installer


    【解决方案1】:

    如果您希望能够以 100% 的准确度处理您的 AssemblyInfo 文件,您可以使用 C# 任务 + 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;
        }
    }
    

    【讨论】:

      【解决方案2】:

      很棒的线程,在 Alex 和 RobPol 的工作的基础上,我能够定义受 semver.org 启发的扩展 msbuild 属性(Major、Minor、Patch、PreRelease)。我选择解析 AssemblyInformalVersion,因为这是与 SemVer 兼容的唯一属性。这是我的例子:

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

      您可以通过将以下内容添加到您的 .csproj 来测试此操作的输出:

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

      例如:来自我的 AssemblyInfo.cs 的片段:

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

      将输出:Major: '0', Minor: '9', Patch: '1', PreRelease: '-beta'

      【讨论】:

      • 很棒的答案。为我工作。
      • 这是 M-A-G-I-C!
      • 我想对这个答案做出甜蜜的爱。
      【解决方案3】:

      基于 Alex 的回答,我使用 RegEx 读取 AssemblyVersion(和其他信息)并将其用于我的 WiX/MSI 文件名和版本字符串。希望我的回答不会太吵。

      这是我的 .wixproj 文件的顶部。兴趣点是第一个 PropertyGroupOutputNameDefineConstants

      <?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>
      

      然后在一个 .wxi 文件中我有这个:

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

      最后在我的 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)" />
      

      【讨论】:

        【解决方案4】:

        您可以从文件中读取行,使用正则表达式获取字符串并根据需要进行更改。如果您使用的是 MSBuild 4.0,则可以使用 Property Functions,它可以让您访问 .NET API。 此示例应为您提供 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

        【讨论】:

          【解决方案5】:

          我刚刚在谷歌上找到了这个,可能会有所帮助:

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

          特别是:

          //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】:

            我使用 MSBuild.Community.Tasks 中的 RegexMatch 任务。

            您可以将匹配的输出写入项目组,尽管您想将其读入 3 个属性,如上所述,然后首选自定义任务。

            【讨论】:

              【解决方案7】:

              您可以使用MSBuild.Community.Tasks.AssemblyInfo.AssemblyVersion 从 AssemblyInfo.cs 中访问 AssemblyVersion 和 AssemblyFileVersion。

              确实这个任务只能用来设置版本。

              也许this post 有用。

              【讨论】:

              【解决方案8】:

              唯一的解决方案是编写自定义构建任务,并在代码中手动解析版本号。

              【讨论】:

              • 没有其他解决方案吗??我可以用正则表达式完成什么?或者是否有任何任务?
              • 好吧,我已经为它编写了自己的任务,并且我使用了简单的字符串方法来解析版本号,但我相信你也可以使用正则表达式来做到这一点。但无论如何,您都必须为此编写自己的任务,除非您找到开箱即用的解决方案。
              猜你喜欢
              • 2016-07-12
              • 1970-01-01
              • 1970-01-01
              • 2020-01-31
              • 1970-01-01
              • 1970-01-01
              • 2011-04-26
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多