2008-10-21 12 views
8

Ich muss mehrere Web-Setup-Projekte (mit VS2005 und ASP.Net/C#) in demselben virtuellen Ordner installieren. Die Projekte teilen einige Assemblyreferenzen (die Dateisysteme sind alle so strukturiert, dass sie denselben "bin" -Ordner verwenden), was die Implementierung von Änderungen an diesen Assemblies problematisch macht, da das MS-Installationsprogramm nur Assemblys überschreibt, wenn die aktuell installierte Version älter ist als die in das MSI.Wie kann ich MSBuild verwenden, um Versionsinformationen nur zu aktualisieren, wenn eine Assembly geändert wurde?

Ich schlage nicht vor, dass das pessimistische Installationsschema falsch ist - nur dass es ein Problem in der Umgebung schafft, mit der ich arbeiten durfte. Da es eine beträchtliche Anzahl von allgemeinen Assemblys und eine beträchtliche Anzahl von Entwicklern gibt, die eine allgemeine Assembly ändern können, aber vergessen, ihre Versionsnummer zu aktualisieren, führt das manuelle Verwalten der Versionierung zu großer Verwirrung bei der Installation.

Auf der anderen Seite dieser Ausgabe, ist es auch wichtig, nicht spontan Versionsnummern zu aktualisieren und alle gemeinsamen Baugruppen mit jeder installieren, da das könnte (zumindest vorübergehend) obskuren Fällen, in denen tatsächliche Änderungen vorgenommen wurden ersetzen.

Das Gesagte, was ich suche, ist ein Mittel zur Aktualisierung der Assemblyversionsinformationen (vorzugsweise mit MSBuild) nur in Fällen, in denen die Baugruppenbestandteile (Codemodule, Ressourcen usw.) tatsächlich geändert haben/haben.

Ich habe ein paar Referenzen gefunden, die zumindest teilweise relevant sind here (AssemblyInfo Aufgabe auf MSDN) und here (sieht ähnlich aus, was ich brauche, aber mehr als zwei Jahre alt und ohne eine klare Lösung).

Mein Team verwendet auch die TFS-Versionskontrolle, daher sollte eine automatisierte Lösung wahrscheinlich ein Mittel enthalten, mit dem die AssemblyInfo während des Builds aus- und eingecheckt werden kann.

Jede Hilfe würde sehr geschätzt werden.

Vielen Dank im Voraus.

Antwort

10

Ich kann nicht alle Ihre Fragen beantworten, da ich keine Erfahrung mit TFS habe.

Aber ich kann einen besseren Ansatz für die Aktualisierung Ihrer AssemblyInfo.cs-Dateien als die Verwendung der AssemblyInfo-Task empfehlen. Diese Aufgabe scheint nur eine Standard-AssemblyInfo-Datei von Grund auf neu zu erstellen und verliert alle benutzerdefinierten Teile, die Sie möglicherweise hinzugefügt haben.

Aus diesem Grund schlage ich vor, dass Sie in der Aufgabe FileUpdate aus dem MSBuild Community Tasks-Projekt nachsehen. Es kann in einer Datei nach bestimmten Inhalten suchen und ersetzen, wie folgt aus:

<FileUpdate 
Files="$(WebDir)\Properties\AssemblyInfo.cs" 
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)" 
ReplacementText="$(Major).$(ServicePack).$(Build).$(Revision)" 
Condition="'$(Configuration)' == 'Release'" 
/> 

Es gibt mehrere Möglichkeiten, wie Sie das Inkrementieren der Build-Nummer steuern kann. Weil ich will nur die Build-Nummer zu erhöhen, wenn der Build vollständig erfolgreich ist, verwende ich ein 2-Stufen-Verfahren:

  • eine Nummer aus einer Textdatei lesen (das einzige, was in der Datei ist die Zahl) und füge 1 ohne die Datei zu ändern;
  • als letzten Schritt im Build-Prozess, wenn alles erfolgreich war, speichern Sie die inkrementierte Zahl zurück in die Textdatei.

Es gibt Aufgaben, wie Readlinesfromfile, das Ihnen dabei helfen kann, aber ich fand es am einfachsten, eine kleine, benutzerdefinierte Aufgabe zu schreiben:

using System; 
using System.IO; 
using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities; 

namespace CredibleCustomBuildTasks 
{ 
    public class IncrementTask : Task 
    { 
     [Required] 
     public bool SaveChange { get; set; } 

     [Required] 
     public string IncrementFileName { get; set; } 

     [Output] 
     public int Increment { get; set; } 

     public override bool Execute() 
     { 
      if (File.Exists(IncrementFileName)) 
      { 
       string lines = File.ReadAllText(IncrementFileName); 
       int result; 
       if(Int32.TryParse(lines, out result)) 
       { 
        Increment = result + 1; 
       } 
       else 
       { 
        Log.LogError("Unable to parse integer in '{0}' (contents of {1})"); 
        return false; 
       } 
      } 
      else 
      { 
       Increment = 1; 
      } 

      if (SaveChange) 
      { 
       File.Delete(IncrementFileName); 
       File.WriteAllText(IncrementFileName, Increment.ToString()); 
      } 
      return true; 
     } 
    } 
} 

Ich benutze dies vor dem FileUpdateTask den nächsten Build zu erhalten Nummer:

<IncrementTask 
IncrementFileName="$(BuildNumberFile)" 
SaveChange="false"> 
    <Output TaskParameter="Increment" PropertyName="Build" /> 
</IncrementTask> 

und als mein letzter Schritt (vor anderen anmelde) im Build:

<IncrementTask 
IncrementFileName="$(BuildNumberFile)" 
SaveChange="true" 
Condition="'$(Configuration)' == 'Release'" /> 

Ihre andere Frage, wie Sie die Versionsnummer nur aktualisieren können, wenn der Quellcode geändert wurde, hängt stark davon ab, wie Ihr Buildprozess mit Ihrer Quellcodeverwaltung interagiert. Normalerweise sollte das Einchecken von Quelldateiänderungen einen Continuous Integration-Build initiieren. Das ist der, der verwendet wird, um die relevante Versionsnummer zu aktualisieren.

0

Ich habe eine custome Aufgabe geschrieben Sie können den Code unten beziehen. Es wird ein Dienstprogramm erstellt, dem Sie den Assembly-Info-Pfad Major, Minor und Build-Nummer übergeben können. Sie können es ändern, um die Revisionsnummer zu erhalten. Da in meinem Fall diese Aufgabe vom Entwickler erledigt wurde, habe ich es gesucht und wieder die ganze Zeichenfolge ersetzt.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Text.RegularExpressions; 

namespace UpdateVersion 
{ 
    class SetVersion 
    { 
     static void Main(string[] args) 
     { 
      String FilePath = args[0]; 
      String MajVersion=args[1]; 
      String MinVersion = args[2]; 
      String BuildNumber = args[3]; 
      string RevisionNumber = null; 

      StreamReader Reader = File.OpenText(FilePath); 
      string contents = Reader.ReadToEnd(); 
      Reader.Close(); 

      MatchCollection match = Regex.Matches(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", RegexOptions.IgnoreCase); 
      if (match[0].Value != null) 
      { 
       string strRevisionNumber = match[0].Value; 

       RevisionNumber = strRevisionNumber.Substring(strRevisionNumber.LastIndexOf(".") + 1, (strRevisionNumber.LastIndexOf("\"")-1) - strRevisionNumber.LastIndexOf(".")); 

       String replaceWithText = String.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]", MajVersion, MinVersion, BuildNumber, RevisionNumber); 
       string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replaceWithText); 

       StreamWriter writer = new StreamWriter(FilePath, false); 
       writer.Write(newText); 
       writer.Close(); 
      } 
      else 
      { 
       Console.WriteLine("No matching values found"); 
      } 
     } 
    } 
} 
0

Ich hasse es zu sagen, aber es scheint, dass Sie es falsch machen können. Ist viel einfacher, wenn Sie die Assembly-Versionen im laufenden Betrieb generieren, anstatt zu versuchen, sie zu patchen.

Werfen Sie einen Blick auf https://sbarnea.com/articles/easy-windows-build-versioning/

Warum ich Sie nicht denken, sind sie falsch? * Ein Build sollte die Versionsnummer nicht ändern * Wenn Sie das gleiche Changeset zweimal erstellen, sollten Sie die gleichen Build-Nummern erhalten * Wenn Sie Build-Nummer in was Microsoft Call Build-Nummer setzen (richtige Namen würde PATCH-Ebene sein) werden Sie schließlich erreichen Sie die 65535 Begrenzung.

Verwandte Themen