65.9K
CodeProject 正在变化。 阅读更多。
Home

在编译时自动增加 Visual Studio 2005 版本号和修订号

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (11投票s)

2006年3月10日

3分钟阅读

viewsIcon

285427

downloadIcon

974

在编译时自动增加 Visual Studio 2005 版本的构建和修订号。

引言

在 Visual Studio 2005 中,当你构建你的项目时,版本号不会自动增加。烦人吗?我认为是。所以,我开始寻找一种方法来实现它。我在网上找到了一些代码示例,说可以做到,虽然它们在某种程度上确实有效,但它们的效果并不好,甚至根本不起作用。

所以,我开始使用从教程中学到的东西来编写我自己的代码。

使用代码

创建一个 Windows DLL 项目,不必是任何特殊的东西。在默认类中,放入以下内容

Imports System
Imports Microsoft.Build.Framework
Imports Microsoft.Build.Utilities

Namespace BuildTasks
    Public Class IncrementBuildNumber
        Inherits Task

        Dim m_AssemblyFileLocation As String 
        ' This is the Assembly file
        ' that has the version info.

        Public Overrides Function _
               Execute() As Boolean
            Try
                Return IncrementVersion()
            Catch ex As Exception
                Log.LogError(ex.Message)
                Return False
            End Try
        End Function 'Execute 

        <Required()> Public Property _
                AssemblyFileLocation() As String
            Get
                Return m_AssemblyFileLocation
            End Get
            Set(ByVal value As String)
                m_AssemblyFileLocation = value
            End Set
        End Property

        Private Function IncrementVersion() As Boolean

            Dim i As Integer
            Dim FileData() As String
            Dim s As String
            Dim Version As String
            Dim v() As String
            Dim ResetRevision As Boolean = True

            ' All the commented msgbox
            ' lines are for debugging.
            ' you don't need them.

            'If MsgBox("IncrementVersion Run on file " & _
                        m_AssemblyFileLocation & _
                        vbNewLine & _
                        vbNewLine & _
                        "Copy path to clipboard?", _
                        MsgBoxStyle.YesNo) = _
                        MsgBoxResult.Yes Then
            '    My.Computer.Clipboard.Clear()
            '    My.Computer.Clipboard.
            '        SetText(m_AssemblyFileLocation)
            'End If


            ' Ok, we have the assembly file, try to open it.
            If IO.File.Exists(m_AssemblyFileLocation) Then

                ' Set build number to the number
                ' of days that have passed since Jan 1 2000
                ' If you want to modifiy what
                ' the build number means or does,
                ' here is the place.
                Dim Major As Integer = 1
                Dim Minor As Integer = 0
                Dim BuildNumber As Integer = _
                   Math.Abs(DateDiff(DateInterval.Day, _
                   Now.Date, CType("JAN/01/2000", Date)))
                Dim Revision As Integer = 0

                'MsgBox("New build number = " & BuildNumber)

                Try
                    FileData = _
                      IO.File.ReadAllLines(m_AssemblyFileLocation)

                    'MsgBox("Read " & FileData.Length & _
                            " lines from " & m_AssemblyFileLocation)

                    If FileData.Length = 0 Then Exit Function
                    ' loop through each line
                    's and look for the version lines.
                    For i = 0 To FileData.Length - 1
                        s = FileData(i)
                        If s.Length > 2 Then
                            ' Look to see if it contains
                            ' one of the 2 version lines we want.
                            'VB: <Assembly: AssemblyVersion("0.0.0.0")> 
                            'VB: <Assembly: AssemblyFileVersion("0.0.0.0")> 
                            'C#: [assembly: AssemblyFileVersion("1.0.0.0")]
                            'C#: [assembly: AssemblyVersion("1.0.0.0")]
                            If Not s.Substring(0, 1) = "'" _
                              And Not s.Substring(0, 2) = "//" Then

                                If s.Contains("AssemblyVersion") _
                                      Or s.Contains("AssemblyFileVersion") Then

                                  'MsgBox("Target line " & s _
                                  '   & " found, parsing now.")

                                  ' Get the version from the line.
                                  ' we do this by getting the first
                                  ' " and losing everything before it.
                                  ' do the same after the next "
                                  ' everything left should be version info.
                                  Version = _
                                      Microsoft.VisualBasic.Right(s, _
                                      s.Length - s.IndexOf(Chr(34)) - 1)
                                  Version = _
                                      Microsoft.VisualBasic.Left(Version, _
                                      Version.IndexOf(Chr(34)))

                                  'MsgBox("Version found = " & Version)

                                  v = Version.Split(".")
                                  If v.Length >= 0 Then
                                      Major = Val(v(0))
                                  If v.Length >= 1 Then
                                      Minor = Val(v(1))
                                  If v.Length >= 2 Then
                                      ResetRevision = _
                                        (BuildNumber <> Val(v(2)))
                                  If v.Length >= 3 Then
                                      Revision = Val(v(3)) + 1

                                  ' ok, now that we have
                                  ' the version numbers in their variables
                                  ' it's time to update
                                  ' the build, if needed.
                                  If ResetRevision Then
                                      Revision = 1

                                  'MsgBox("Replacing version with " _
                                  '& Major & "." & Minor & "." & _
                                  'BuildNumber & "." & Revision)

                                  ' ok, update the original
                                  ' line from the array.
                                  FileData(i) = _
                                    FileData(i).Replace(Version, _
                                    Major & "." & Minor & "." & _
                                    BuildNumber & "." & Revision)

                                  'MsgBox("Filedata(" & i _
                                  '   & ") = " & FileData(i))
                                End If
                            End If
                        End If
                    Next

                    ' ok, rewrite the assembly info back
                    ' into the file, and let's home
                    ' the compiler picks it up
                    'MsgBox("writing all data back to file")
                    IO.File.WriteAllLines(m_AssemblyFileLocation, _
                                                        FileData)


                Catch ex As Exception
                    ' hrm. Error. Fail please.
                    MsgBox("ERROR! " & ex.Message, "Build Tasks")
                    Log.LogError(ex.Message)
                    Return False
                End Try
            End If

            ' return success
            Return True
        End Function

    End Class
End Namespace

现在...我们怎么使用它?我的意思是,你现在有一个很棒的 DLL 文件了...但它如何应用于你的项目呢?首先,你需要将你的 DLL 复制到与你的项目文件相同的文件夹中。不要将“解决方案”文件 (.sln) 与你的项目文件 (.vbproj) 混淆,因为它们不是同一回事。

一旦文件被复制,在记事本或其他文本编辑器中打开 .vbproj 文件,这样你就可以看到原始信息了。

<project> 标签之后和第一个 <propertygroup> 标签之前,将以下行添加到项目文件中。

<UsingTask TaskName="BuildTasks.IncrementBuildNumber" 
            AssemblyFile="BuildTask.dll" />

我的一个项目文件的示例如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="BuildTasks.IncrementBuildNumber" 
     AssemblyFile="BuildTask.dll" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">
               Debug</Configuration>
    
    ...

一直向下滚动直到你找到 <Target Name="BeforeBuild"> 标签。它可能被注释掉了;取消注释,并在开始和结束标签之间添加以下内容

<IncrementBuildNumber AssemblyFileLocation = 
    "$(MSBuildProjectDirectory)\My Project\AssemblyInfo.vb">
</IncrementBuildNumber>

注意! 确保你的程序集文件的路径是正确的。如果它不在 "My Projects" 文件夹中,请确保你调整上面的行以说明它在哪里。$(MSBuildProjectDirectory) 变量将被替换为 .vbproj 文件所在的文件夹。因此,如果 assembly.vb 文件位于同一位置,则不要使用任何子文件夹。默认情况下,VS 2005 将其放在 "My Projects" 文件夹中并将其命名为 AssemblyInfo.vb。对于 C#,它是 AssemblyInfo.cs

这个 DLL 应该适用于 C# 和 VB 项目,而且应该适用于所有 VS 项目...但我只用 C# 和 VB 进行了测试。

保存项目文件,然后在 VS 中打开它。现在,每次你构建项目时,VS 将调用 DLL 中的 IncrementBuildNumber 类并执行其中的代码。代码本身打开你的程序集文件,编辑版本信息,然后保存它。

因为你在 "BeforeBuild" 部分执行此操作,所以它将在你构建之前完成。很棒吧?

注意:一些项目文件可能没有 <Target Name="BeforeBuild"> 标签。如果是这种情况,我通常只是在 <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" /> 行之后添加它们。

例如:

<Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
<Target Name="BeforeBuild">
  <IncrementBuildNumber AssemblyFileLocation=
           "$(MSBuildProjectDirectory)\AssemblyInfo.vb">
  </IncrementBuildNumber>
  </Target>
  <Target Name="AfterBuild">
  </Target>
</Project>

关注点

有时,修订号会跳 2 或 3 个数字。我不知道为什么,我只能假设某些东西没有正确重新加载,或者编译器调用了 DLL 两次或更多次。实际上,我真的不在乎,所以我从未费心去修复它。

此外,如果你打开了项目属性窗口或程序集文件,版本可能不会增加。同样,我没有足够关心这么小的事情,所以没有花时间去尝试修复它。如果你知道原因,请随时告诉我。

历史

  • 1.0.0.0 - 初始发布。
© . All rights reserved.