2008-10-21 14 views
8

Tengo un requerimiento para instalar múltiples proyectos de configuración web (usando VS2005 y ASP.Net/C#) en la misma carpeta virtual. Los proyectos comparten algunas referencias de ensamblaje (todos los sistemas de archivos están estructurados para usar la misma carpeta 'bin'), lo que dificulta el despliegue de cambios en esos ensamblajes ya que el instalador MS solo sobrescribirá ensamblajes si la versión instalada actualmente es anterior a la el MSI.¿Cómo puedo usar MSBuild para actualizar la información de la versión solo cuando ha cambiado un ensamblaje?

No estoy sugiriendo que el esquema de instalación pesimista sea incorrecto, solo que crea un problema en el entorno con el que he trabajado. Debido a que hay un número considerable de ensambles comunes y un número significativo de desarrolladores que pueden cambiar un ensamblaje común, pero se olvidan de actualizar su número de versión, tratar de administrar las versiones manualmente conducirá finalmente a una confusión masiva en el momento de la instalación.

En la otra cara de este tema, también es importante que no se actualice de forma espontánea números de versión y reemplazar todos asambleas comunes con cada instalar, ya que los casos oscuros podría (al menos temporalmente) que se hicieron cambios reales.

Dicho esto, lo que estoy buscando es un medio para actualizar la información de la versión del ensamblado (preferiblemente usando MSBuild) solo en casos donde los componentes del ensamblaje (módulos de código, recursos, etc.) hayan/hayan cambiado realmente.

He encontrado algunas referencias que son al menos parcialmente pertinentes here (tarea AssemblyInfo en MSDN) y here (se parece a lo que necesito, pero con más de dos años y sin una solución clara).

Mi equipo también utiliza el control de versiones TFS, por lo que una solución automatizada probablemente debería incluir un medio por el cual AssebmlyInfo se pueda extraer/registrar durante la compilación.

Cualquier ayuda sería muy apreciada.

Gracias de antemano.

Respuesta

10

No puedo responder todas sus preguntas, ya que no tengo experiencia con TFS.

Pero puedo recomendar un mejor enfoque para actualizar sus archivos AssemblyInfo.cs que utilizar la tarea AssemblyInfo. Esa tarea parece recrear un archivo AssemblyInfo estándar desde cero y pierde cualquier parte personalizada que haya agregado.

Por esa razón, le sugiero que consulte la tarea FileUpdate, del proyecto MSBuild Community Tasks. Puede buscar contenido específico en un archivo y sustituirlo, así:

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

Hay varias maneras que usted puede controlar la incrementación del número de compilación. Porque yo sólo quiero el número de compilación a medida si la construcción es un éxito completo, utilizo un método de 2 pasos:

  • leer un número de un archivo de texto (la única cosa en el archivo es el número) y añadir 1 sin cambiar el archivo;
  • como paso final en el proceso de compilación, si todo tuvo éxito, guarde el número incrementado nuevamente en el archivo de texto.

Hay tareas tales como ReadLinesFromFile, que le puede ayudar con esto, pero me pareció más fácil de escribir una pequeña tarea personalizada:

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

utilizo esto antes de la FileUpdateTask para obtener la próxima construcción número:

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

y como mi paso final (antes de notificar a otros) en la construcción:

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

Su otra pregunta sobre cómo actualizar el número de versión solo cuando el código fuente ha cambiado depende en gran medida de cómo su proceso de compilación interactúa con su control de origen. Normalmente, el control de los cambios en el archivo fuente debe iniciar una compilación de integración continua. Ese es el que debe usar para actualizar el número de versión correspondiente.

0

He escrito una tarea específica, puede consultar el siguiente código. Creará una utilidad a la que puede pasar la ruta de información de ensamblaje Mayor, menor y número de compilación. puedes modificarlo para obtener el número de revisión. Dado que en mi caso esta tarea fue realizada por el desarrollador, solía buscarla y nuevamente reemplazar toda la cadena.

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

Odio decir esto, pero parece que puede estar haciendo mal. Es mucho más fácil si genera las versiones de ensamblaje sobre la marcha en lugar de tratar de parchearlas.

Tome un vistazo a https://sbarnea.com/articles/easy-windows-build-versioning/

Por qué yo creo que lo está haciendo mal? * Una compilación no debería modificar el número de versión * si construyes el mismo conjunto de cambios dos veces deberías obtener los mismos números de compilación * si pones el número de compilación dentro de qué número de compilación de llamadas microsoft (nombre apropiado sería PATCH) eventualmente alcanzar la limitación 65535

Cuestiones relacionadas