Imports EnvDTE
Imports System
Imports System.IO
Imports System.Diagnostics
Imports System.Text.RegularExpressions
Imports Extensibility
Imports Microsoft.Office.Core
Imports System.Runtime.InteropServices
' Build Number Automation Error
' By Darrel Liu, 9/11/2003
' Modified extensively by Paul Heap 10/2/2002
' Compiled and tested under Visual Studio .NET 2002
Public Class VersionControl
Public DTE As EnvDTE.DTE
Public OutputWindowPane As OutputWindowPane
' The date this project started, used to calculate the build number
ReadOnly theProjectStartingDate As DateTime = New DateTime(2003, 6, 22)
' Path to file AssemblyInfo.cs, relative to path of the project
ReadOnly theAssemblyInfoFilePathvb As String = "AssemblyInfo.vb"
ReadOnly theAssemblyInfoFilePathcsharp As String = "AssemblyInfo.cs"
' Regular expression to match the version string
'ReadOnly theVersionString As String = "AssemblyVersion\(" & Chr(34) & "[0-9]\.[0-9]\.([0-9\.]+)" & Chr(34) & "\)"
Dim weHitGold As String = "AssemblyVersion(" & """"
Dim theVersionString As String = "AssemblyVersion\(" & """" & "|[0-9]+|\*"
' Set whether to build the solution after updating the build number
ReadOnly theBuildSolution As Boolean = False
' Routine to modify the build number in file AssemblyInfo.cs automatically
Sub BuildNumberAutomation(ByVal theBuildingProjectFileName As String)
Dim aProject As Project
Dim aVSProject As VSLangProj.VSProject
Dim aProjectPath As String
Try
For Each aProject In DTE.Solution.Projects.DTE.GetObject("CSharpProjects")
aProjectPath = aProject.Properties.Item("FullPath").Value
' is theBuildingProjectFileName in aProject.FileName?
If theBuildingProjectFileName.ToString.IndexOf(aProject.Name) >= 0 Then
ModifyBuildNumber(aProjectPath & theAssemblyInfoFilePathcsharp, aProject.Name)
End If
Next
For Each aProject In DTE.Solution.Projects.DTE.GetObject("VBProjects")
aProjectPath = aProject.Properties.Item("FullPath").Value
If theBuildingProjectFileName.ToString.IndexOf(aProject.Name) >= 0 Then
ModifyBuildNumber(aProjectPath & theAssemblyInfoFilePathvb, aProject.Name)
End If
Next
Catch e As Exception
WriteToOutputBuildPane("Unknown Build Number Automation error captured : " & e.Message)
Exit Sub
End Try
If theBuildSolution Then
DTE.ExecuteCommand("Build.BuildSolution")
End If
End Sub
Private Sub ModifyBuildNumber(ByVal aFilePath As String, ByVal aProjectName As String)
Dim aFileContent As String
Dim aVersionStringRegEx As Regex
Dim aMatch As Match
Dim SomeMatches As MatchCollection
Dim VersionArray As Collection
Dim Version1, Version2, Version3, Version4 As String
Dim VersionID As Integer = -1
Dim aMatchValue As String
Dim Third, Fourth As String
Dim hitastar As Boolean = False
Try
WriteToOutputBuildPane("...Updating Version Info for " & aProjectName & "...")
aFileContent = ReadFileContent(aFilePath)
aVersionStringRegEx = New Regex(theVersionString)
SomeMatches = aVersionStringRegEx.Matches(aFileContent)
Dim AreWeCookingOnGasYet As Boolean = False
For Each aMatch In SomeMatches
If aMatch.Value = weHitGold Then
AreWeCookingOnGasYet = True
Fourth = CalculateBuildNumber()
End If
If AreWeCookingOnGasYet Then
VersionID += 1
'WriteToOutputBuildPane(VersionID & " : " & aMatch.Value)
If VersionID = 3 Then
aFileContent = aFileContent.Remove(aMatch.Index, aMatch.Length)
If aMatch.Value = "*" Then
hitastar = True
aFileContent = aFileContent.Insert(aMatch.Index, "0.0")
Else : aFileContent = aFileContent.Insert(aMatch.Index, CStr((CInt(aMatch.Value) + 1)))
End If
End If
If VersionID = 4 Then
If Not hitastar Then
aFileContent = aFileContent.Remove(aMatch.Index, aMatch.Length)
aFileContent = aFileContent.Insert(aMatch.Index, Fourth)
End If
End If
End If
Next
If WriteFileContent(aFilePath, aFileContent) Then
WriteToOutputBuildPane("Updated version information successfully.")
Else
WriteToOutputBuildPane("Failed to update version information.")
End If
Catch ex As Exception
WriteToOutputBuildPane("Critical error building the version number " & ex.Message)
End Try
End Sub
' Read file content to a string
Private Function ReadFileContent(ByVal aFilePath As String) As String
Dim aFile As FileStream
Dim aFileReader As StreamReader
Dim aFileContent As String
Try
aFile = New FileStream(aFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
aFileReader = New StreamReader(aFile)
Catch e As FileNotFoundException
WriteToOutputBuildPane("Could not find file to read: " & aFilePath)
Exit Function
End Try
aFileContent = aFileReader.ReadToEnd()
aFileReader.Close()
Return aFileContent
End Function
' Write the modified file content back
Private Function WriteFileContent(ByVal aFilePath As String, ByVal aFileContent As String) As Boolean
Dim aFile As FileStream
Dim aFileWriter As StreamWriter
Try
WriteFileContent = False
Try
aFile = New FileStream(aFilePath, FileMode.Open, FileAccess.Write, FileShare.Read)
aFileWriter = New StreamWriter(aFile)
Catch e As FileNotFoundException
WriteToOutputBuildPane("Could not find file to write: " & aFilePath)
Exit Function
End Try
Try
aFileWriter.Write(aFileContent)
aFileWriter.BaseStream.SetLength(aFileContent.Length)
aFileWriter.Flush()
Finally
aFileWriter.Close()
End Try
WriteFileContent = True
Catch e As Exception
WriteToOutputBuildPane("Unable to update assemblyinfo file : " & aFilePath & ", Reason : " & e.message)
WriteFileContent = False
Exit Function
End Try
End Function
' Calculate the build number based on the following rules:
' For instance: version "AA.BB.CCDD.EEFF"
' where AA - Major version number (manually set)
' BB - Minor version number (manually set)
' CCDD - DD'th day of CC'th month since the beginning of the project
' EEFF - EE hours and FF minutes in that day the build was created
Private Function CalculateBuildNumber() As String
Dim aBuildNumber As String = ""
Dim aBuildDate As DateTime = DateTime.Now
Dim aTempDate As DateTime
Dim aDateDiff As TimeSpan
Try
Dim aMonthsDifference As Integer = aBuildDate.Month - theProjectStartingDate.Month
Dim aDaysDifference As Integer = aBuildDate.Day - theProjectStartingDate.Day
If aDaysDifference < 0 Then
aDateDiff = New TimeSpan(DateTime.DaysInMonth(aBuildDate.Year, aBuildDate.Month), 0, 0, 0)
aTempDate = aBuildDate.Subtract(aDateDiff)
aDateDiff = New TimeSpan(-aDaysDifference, 0, 0, 0)
aTempDate = aTempDate.Add(aDateDiff)
aMonthsDifference = DateDiff(DateInterval.Month, theProjectStartingDate, aTempDate)
aDaysDifference = DateDiff(DateInterval.Day, aTempDate, aBuildDate)
End If
' aBuildNumber += Format(aMonthsDifference, "00")
' aBuildNumber += Format(aDaysDifference, "00")
' ThirdNo = Format(aMonthsDifference, "00") & Format(aDaysDifference, "00")
' aBuildNumber += "."
' aBuildNumber += Format(aBuildDate.Hour, "00")
' aBuildNumber += Format(aBuildDate.Minute, "00")
' FourthNo = Format(aBuildDate.Hour, "00") & Format(aBuildDate.Minute, "00")
' PAUL: I only want the day and month
aBuildNumber += Format(aBuildDate.Day, "00")
aBuildNumber += Format(aBuildDate.Month, "00")
' aBuildNumber += Format(aBuildDate.Year, "00")
Return aBuildNumber
Catch ex As Exception
WriteToOutputBuildPane("Error calculating the Build Number : " & ex.Message)
End Try
End Function
' ----------------------------------
' write text message to a log file
' ----------------------------------
Sub WriteToLogFile(ByVal msg_text As String)
Dim log_filename As String
log_filename = DTE.Solution.FullName
log_filename = Path.ChangeExtension(log_filename, ".log.txt")
Try
Dim sw As StreamWriter = File.AppendText(log_filename)
sw.WriteLine(msg_text)
sw.Close()
Catch ex As Exception
WriteToOutputBuildPane("Log file write failed : " & ex.Message)
End Try
End Sub
' ----------------------------------------------------------------
' write a text message to the build pane of the output tool window
' ----------------------------------------------------------------
Sub WriteToOutputBuildPane(ByVal msg_text As String)
OutputWindowPane.OutputString(msg_text & ControlChars.Lf)
End Sub
End Class