AssemblyInfo.cs文件中更新程序集内部版本号的正则表达式是什么?

时间:2009-07-21 05:54:02

标签: regex

现在,我正在编写VS 2008宏来替换AssemblyInfo.cs文件中的Assembly版本。从MSDN,必须使用以下模式编写程序集版本。

  

MAJOR.MINOR [.build [.revision]]

示例

  • 1.0
  • 1.0.1234
  • 1.0.1234.0

我需要为'AssemblyInfo.cs'文件动态生成内部版本号,并使用正则表达式将旧版本号替换为新生成的内部版本号。

你有任何正则表达式来解决这个问题吗?此外,构建号不得包含在注释语句中,如下面的代码。最后,不要忘记查看正则表达式的内联注释。

请勿替换任何已评论的内部版本号

//[assembly: AssemblyVersion("0.1.0.0")]

/*[assembly: AssemblyVersion("0.1.0.0")]*/

/*
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("0.1.0.0")]
 */

替换未注释的内部版本号

[assembly: AssemblyVersion("0.1.0.0")] // inline comment
/* inline comment */ [assembly: AssemblyVersion("0.1.0.0")]
[assembly: /*inline comment*/AssemblyVersion("0.1.0.0")]

提示。

请在Online Regular Expression Testing Tool

尝试你的正则表达式

4 个答案:

答案 0 :(得分:3)

这有些粗糙,但您可以执行以下操作。

搜索:

^{\[assembly\: :w\(\"0\.1\.}\*

替换为:

\1####

其中####是您的替换字符串。

这个正则表达式的工作原理如下:

  1. 首先搜索以 \ [assembly \:开头的行,( ^ 表示行的开头,反斜杠转义特殊字符)后跟...
  2. ...一些字母标识符:w ,其次是......
  3. ......开口大括号 \(,其次是......
  4. ...版本字符串的开头,引号 \“0 \ .1 \。,最后跟着......
  5. ...星号 \ *
  6. 使用围绕它们的花括号 {} 将步骤1-4捕获为第一个带标记的表达式。
  7. 替换字符串逐字地删除标记的表达式,因此不会受到: \ 1 ,然后是替换字符串,一些####。
  8. 注释行被忽略,因为它们不以[assembly:。后续的内嵌注释保持不变,因为它们未被正则表达式捕获。

    如果这不是您所需要的,那么试验正则表达式以捕获和/或替换该行的不同部分是相当简单的。

答案 1 :(得分:0)

我怀疑使用正则表达式会对你有好处。虽然可以制定一个与“未注释”的汇编版本属性相匹配的表达式,但它很难维护和理解。

您使用您提供的语法对自己非常努力。如何在AssemblyInfo.cs文件中强制执行编码标准,该文件应始终使用开头//并禁止内联注释注释掉行?然后,使用StreamReader解析它应该很容易。

如果你不能这样做,那么只有一个解析器可以保证处理所有边缘情况,那就是C#编译器。如何编译程序集然后反映它以检测版本号?

var asm = Assembly.LoadFile("foo.dll");
var version = Assembly.GetExecutingAssembly().GetName().Version;

如果您只是想增加内置编号,那么您应该看一下这个问题:Can I automatically increment the file build version when using Visual Studio?

答案 2 :(得分:0)

我只是找到了我的问题的答案。但答案非常复杂。很长的正则表达式。顺便说一句,我每个解决方案只使用这种语法一次。因此,它不会影响整体性能。请查看我的完整源代码。

模块EnvironmentEvents.vb

Public Module EnvironmentEvents
    Private Sub BuildEvents_OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildBegin
        If DTE.Solution.FullName.EndsWith(Path.DirectorySeparatorChar & "[Solution File Name]") Then
            If Scope = vsBuildScope.vsBuildScopeSolution And Action = vsBuildAction.vsBuildActionRebuildAll Then
                AutoGenerateBuildNumber()
            End If
        End If
    End Sub
End Module

模块AssemblyInfoHelp.vb

Public Module AssemblyInfoHelper

    ReadOnly AssemblyInfoPath As String = Path.Combine("Common", "GlobalAssemblyInfo.cs")

    Sub AutoGenerateBuildNumber()

        'Declear required variables
        Dim solutionPath As String = Path.GetDirectoryName(DTE.Solution.Properties.Item("Path").Value)
        Dim globalAssemblyPath As String = Path.Combine(solutionPath, AssemblyInfoPath)
        Dim globalAssemblyContent As String = ReadFileContent(globalAssemblyPath)
        Dim rVersionAttribute As Regex = New Regex("\[[\s]*(\/\*[\s\S]*?\*\/)?[\s]*assembly[\s]*(\/\*[\s\S]*?\*\/)?[\s]*:[\s]*(\/\*[\s\S]*?\*\/)?[\s]*AssemblyVersion[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\([\s]*(\/\*[\s\S]*?\*\/)?[\s]*\""([0-9]+)\.([0-9]+)(.([0-9]+))?(.([0-9]+))?\""[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\)[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\]")
        Dim rVersionInfoAttribute As Regex = New Regex("\[[\s]*(\/\*[\s\S]*?\*\/)?[\s]*assembly[\s]*(\/\*[\s\S]*?\*\/)?[\s]*:[\s]*(\/\*[\s\S]*?\*\/)?[\s]*AssemblyInformationalVersion[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\([\s]*(\/\*[\s\S]*?\*\/)?[\s]*\""([0-9]+)\.([0-9]+)(.([0-9]+))?[\s]*([^\s]*)[\s]*(\([\s]*Build[\s]*([0-9]+)[\s]*\))?\""[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\)[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\]")

        'Find Version Attribute for Updating Build Number
        Dim mVersionAttributes As MatchCollection = rVersionAttribute.Matches(globalAssemblyContent)
        Dim mVersionAttribute As Match = GetFirstUnCommentedMatch(mVersionAttributes, globalAssemblyContent)
        Dim gBuildNumber As Group = mVersionAttribute.Groups(9)
        Dim newBuildNumber As String

        'Replace Version Attribute for Updating Build Number
        If (gBuildNumber.Success) Then
            newBuildNumber = GenerateBuildNumber(gBuildNumber.Value)
            globalAssemblyContent = globalAssemblyContent.Substring(0, gBuildNumber.Index) + newBuildNumber + globalAssemblyContent.Substring(gBuildNumber.Index + gBuildNumber.Length)
        End If

        'Find Version Info Attribute for Updating Build Number
        Dim mVersionInfoAttributes As MatchCollection = rVersionInfoAttribute.Matches(globalAssemblyContent)
        Dim mVersionInfoAttribute As Match = GetFirstUnCommentedMatch(mVersionInfoAttributes, globalAssemblyContent)
        Dim gBuildNumber2 As Group = mVersionInfoAttribute.Groups(12)

        'Replace Version Info Attribute for Updating Build Number
        If (gBuildNumber2.Success) Then
            If String.IsNullOrEmpty(newBuildNumber) Then
                newBuildNumber = GenerateBuildNumber(gBuildNumber2.Value)
            End If

            globalAssemblyContent = globalAssemblyContent.Substring(0, gBuildNumber2.Index) + newBuildNumber + globalAssemblyContent.Substring(gBuildNumber2.Index + gBuildNumber2.Length)
        End If

        WriteFileContent(globalAssemblyPath, globalAssemblyContent)

    End Sub

    Function GenerateBuildNumber(Optional ByVal oldBuildNumber As String = "0") As String

        oldBuildNumber = Int16.Parse(oldBuildNumber) + 1

        Return oldBuildNumber

    End Function

    Private Function GetFirstUnCommentedMatch(ByRef mc As MatchCollection, ByVal content As String) As Match
        Dim rSingleLineComment As Regex = New Regex("\/\/.*$")
        Dim rMultiLineComment As Regex = New Regex("\/\*[\s\S]*?\*\/")

        Dim mSingleLineComments As MatchCollection = rSingleLineComment.Matches(content)
        Dim mMultiLineComments As MatchCollection = rMultiLineComment.Matches(content)

        For Each m As Match In mc
            If m.Success Then
                For Each singleLine As Match In mSingleLineComments
                    If singleLine.Success Then
                        If m.Index >= singleLine.Index And m.Index + m.Length <= singleLine.Index + singleLine.Length Then
                            GoTo NextAttribute
                        End If
                    End If
                Next

                For Each multiLine As Match In mMultiLineComments
                    If multiLine.Success Then
                        If m.Index >= multiLine.Index And m.Index + m.Length <= multiLine.Index + multiLine.Length Then
                            GoTo NextAttribute
                        End If
                    End If
                Next

                Return m
            End If
NextAttribute:
        Next

        Return Nothing

    End Function

End Module

谢谢大家

PS。特别感谢[RegExr:在线正则表达式测试工具] [1]。我曾经玩过的最好的在线正则表达式工具。 [1]:http://gskinner.com/RegExr/

答案 3 :(得分:0)

通过下载并安装MS Build Extension Pack并在.csproj文件的顶部添加以下行,您可以更轻松地实现同样的效果:

<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.VersionNumber.targets"/>

这将自动使用当前日期(MMdd)作为内部版本号,并为您增加修订号。现在,要覆盖次要版本和主要版本(默认设置为1.0),只需在.csproj文件中的任何位置添加以下内容:

<PropertyGroup>
 <AssemblyMajorVersion>2</AssemblyMajorVersion>
 <AssemblyFileMajorVersion>1</AssemblyFileMajorVersion> 
</PropertyGroup>

您可以通过为属性列表设置其他属性see this page来进一步自定义构建号和修订版的生成方式,甚至可以设置公司,版权等。