2009-08-09 20 views
12

¿Cómo se puede leer la AssemblyFileVersion, o sus componentes AssemblyFileMajorVersion, AssemblyFileMinorVersion, AssemblyFileBuildNumber, AssemblyFileRevision, dentro del .csproj, tras la compilación?Leer AssemblyFileVersion de AssemblyInfo post-compilar

me han tratado los siguientes elementos que tira de la información del conjunto de construcción:

<Target Name="AfterCompile"> 
    <GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> 
     <Output 
      TaskParameter="Assemblies" 
      ItemName="MyAssemblyIdentities"/> 
    </GetAssemblyIdentity> 
    <Message Text="AssemblyVersion = %(MyAssemblyIdentities.Version)" /> 
</Target> 

Pero que recupera la AssemblyVersion y no AssemblyFileVersion. No parece haber una entrada de metadatos documentada para este último. También probé:

<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks" /> 
<Target Name="AfterCompile"> 
    <MSBuild.ExtensionPack.Framework.Assembly TaskAction="GetInfo" NetAssembly="$(TargetPath)"> 
     <Output TaskParameter="OutputItems" ItemName="Info" /> 
    </MSBuild.ExtensionPack.Framework.Assembly> 
    <Message Text="AssemblyFileVersion = %(Info.FileVersion)" /> 
</Target> 

Lamentablemente, si bien esta recupera el valor correcto, sino que también el archivo cerraduras el conjunto hasta que VS2008 está cerrado.

Francamente, tampoco es lo que quiero ya que preferiría leer la información de AssemblyInfo.cs directamente. Sin embargo, no puedo encontrar la manera de hacerlo. Supuse que AssemblyInfo en MSBuild Extensions era de una sola manera, pero parece enfocado en escribir en AssemblyInfo y no recuperar valores de él.

¿Cómo puedo lograr esto?

+2

+1 simplemente por preguntar "¿Cómo lo leo?" En lugar de lo que siempre encuentras: Cómo actualizar la información de la versión. – Yoopergeek

+0

Como han pasado dos meses desde que pregunté esto y la única respuesta utilizable es la mía, la aceptaré. Sigo pensando que puede haber una mejor manera. – Gregyski

+0

@Yoopergeek: De hecho, hay varios métodos para escribir, pero la lectura fue difícil incluso después de una gran cantidad de investigaciones. Mi respuesta a continuación, sin embargo, funciona bien. – Gregyski

Respuesta

11

he conseguido solucionar esto usando una tarea personalizada. La DLL de biblioteca de clases es tan así (algo de código ajustado/eliminado por razones de brevedad):

using System; 
using System.IO; 
using System.Text.RegularExpressions; 
using Microsoft.Build.Framework; 

namespace GetAssemblyFileVersion 
{ 
    public class GetAssemblyFileVersion : ITask 
    { 
     [Required] 
     public string strFilePathAssemblyInfo { get; set; } 
     [Output] 
     public string strAssemblyFileVersion { get; set; } 
     public bool Execute() 
     { 
      StreamReader streamreaderAssemblyInfo = null; 
      Match matchVersion; 
      Group groupVersion; 
      string strLine; 
      strAssemblyFileVersion = String.Empty; 
      try 
      { 
       streamreaderAssemblyInfo = new StreamReader(strFilePathAssemblyInfo); 
       while ((strLine = streamreaderAssemblyInfo.ReadLine()) != null) 
       { 
        matchVersion = Regex.Match(strLine, @"(?:AssemblyFileVersion\("")(?<ver>(\d*)\.(\d*)(\.(\d*)(\.(\d*))?)?)(?:""\))", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.ExplicitCapture); 
        if (matchVersion.Success) 
        { 
         groupVersion = matchVersion.Groups["ver"]; 
         if ((groupVersion.Success) && (!String.IsNullOrEmpty(groupVersion.Value))) 
         { 
          strAssemblyFileVersion = groupVersion.Value; 
          break; 
         } 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       BuildMessageEventArgs args = new BuildMessageEventArgs(e.Message, string.Empty, "GetAssemblyFileVersion", MessageImportance.High); 
       BuildEngine.LogMessageEvent(args); 
      } 
      finally { if (streamreaderAssemblyInfo != null) streamreaderAssemblyInfo.Close(); } 
      return (true); 
     } 
     public IBuildEngine BuildEngine { get; set; } 
     public ITaskHost HostObject { get; set; } 
    } 
} 

Y en el archivo del proyecto:

<UsingTask AssemblyFile="GetAssemblyFileVersion.dll" TaskName="GetAssemblyFileVersion.GetAssemblyFileVersion" /> 
<Target Name="AfterCompile"> 
    <GetAssemblyFileVersion strFilePathAssemblyInfo="$(SolutionDir)\AssemblyInfo.cs"> 
     <Output TaskParameter="strAssemblyFileVersion" PropertyName="strAssemblyFileVersion" /> 
    </GetAssemblyFileVersion> 
    <Message Text="AssemblyFileVersion = $(strAssemblyFileVersion)" /> 
</Target> 

He probado esto y leerá la versión actualizada si utiliza MSBuild.ExtensionPack.VersionNumber.targets para la creación automática de versiones.

Obviamente, esto podría extenderse fácilmente de modo que se pase una expresión regular desde el archivo de proyecto a una tarea personalizada de propósito más general para obtener cualquier coincidencia en cualquier archivo.


Actualizar 2009/09/03:

Un cambio adicional tiene que ser hecho para hacer la actualización ApplicationVersion en cada generación. InitialTargets="AfterCompile" se debe agregar al <Project.... Esto fue solved by Chao Kuo.

+0

Tenga en cuenta que la expresión regular utilizada anteriormente es una modificación de la respuesta de Jonathan Leffler para el artículo SO "Hacer coincidir las partes del número de versión con expresiones regulares" @ http://stackoverflow.com/questions/400522/matching-version-number-parts-with -expresiones regulares – Gregyski

0

¿Qué tal copiar el assmelby y luego ejecutar la tarea de ensamblaje en la copia?

Sayed Ibrahim Hashimi

+0

Me gustaría encontrar algo un poco más elegante, pero lo intentaré. Sin embargo, tendré que comprobar si eso funcionará para compilaciones posteriores o si el error de bloqueo del archivo obstruirá las copias futuras. Si lo hace, tendré que copiar a un nombre de archivo diferente cada vez, lo que se está volviendo aún más poco elegante. Te dejaré saber cómo va. Gracias. – Gregyski

1

Si hace que la tarea se herede de AppDomainIsolatedTask, no necesita cargar el conjunto desde las secuencias. Solo puede usar AppDomain.LoadFrom (file).

Cuestiones relacionadas