2012-01-05 18 views
11

Estoy escribiendo un archivo por lotes para automatizar una serie de tareas. Una de estas tareas es actualizar la versión de los dlls en mi solución, editando el archivo assemblyinfo.cs en los diversos proyectos en mi solución; y finalmente llamando a msbuild.exe para compilar la solución.MSbuild para actualizar el archivo de información de montaje

En este sentido, es posible escribir un script de línea de comandos para actualizar los diversos archivos de assemblyinfo.cs en mi solución .net. Preferiría llamar a msbuild desde la propia línea de comandos y no crear otro archivo con scripts de msbuild.

¿Cómo se hace esto con MSBuild? ¿Hay alguna otra forma de hacerlo?

Gracias por su tiempo ...

+0

Utilice msbuild: http://stackoverflow.com/questions/4562845/how-can-i-change-assembly-version-number-using-assemblyinfotask/4970347#4970347 –

+2

¿Tiene el votante de abajo una razón para bajar ¿Vota o es el votante a la baja que acaba de tener un mal día? – user20358

Respuesta

9

Edición de archivos con el DOS archivos por lotes cmd es bastante peluda sin la ayuda de otras herramientas. Debería usar algo como el comando for/f para recorrer las líneas y luego procesar cada línea. Por ejemplo, busque la línea que comienza: "[assembly: AssemblyVersion" y reemplácela por otra cosa.

Sin embargo, si no tiene mucho en su AssemblyInfo.cs (y recuerde que puede dividir AssemblyInfo.cs en varios archivos cs si lo desea) le sugiero crear el archivo desde cero con un par de eco declaraciones.

Si tiene otras herramientas disponibles como sed.exe, las ediciones se pueden realizar fácilmente.

Mi preferencia en estos días sería ir a un script trivial powershell, que podría comer esto para el desayuno y le da acceso a las bibliotecas .Net si lo necesita.

Aquí es una forma de plantillas de ella:

(Get-Content AssemblyInfo.template.cs) -replace "{version}","1.2.3.4" > AssemblyInfo.cs 

Aquí hay un formulario que utiliza expresiones regulares para reemplazar cualquiera que sea el número de versión está ahí:

$x = 'Version("{0}")' -f "1.2.3.4" 
$content = Get-Content AssemblyInfo.cs 
$content -replace 'Version\(".*"\)',$x > AssemblyInfo.cs 
+0

No sé expresiones regulares. Probé la línea que sugirió arriba y limpió el archivo AssemblyInfo.cs. – user20358

+1

Lo siento, la tubería estaba truncando el archivo original antes de que se completara o comenzara a leerlo. He editado el ejemplo con una solución para leer el contenido original como un paso separado. – StephenD

7

¿No hay un MS Construir tarea para modificar el assemblyInfo.cs

tenemos algo como esto en nuestro publish.proj

<Target Name="SolutionInfo"> 
    <Message Text="Creating Version File:  $(Major).$(Minor).$(Build).$(Revision)"/> 


<AssemblyInfo 
     CodeLanguage="CS" 
     OutputFile="$(BuildInputDir)\SolutionInfo.cs" 
     AssemblyTitle="$(Company) $(Product)$(ProductAppendix)" 
     AssemblyDescription="$(Company) $(Product)$(ProductAppendix)" 
     AssemblyCompany="$(Company)" 
     AssemblyProduct="$(Product)" 
     AssemblyCopyright="Copyright © $(Company)"  
     ComVisible="false" 
     CLSCompliant="false" 
     Guid="9E77382C-5FE3-4313-B099-7A9F24A4C328" 
     AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)" 
     AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" /> 
</Target> 
+0

¿Puedo poner eso en mi archivo por lotes? Estoy buscando algo que pueda llamar desde mi archivo de proceso por lotes, así que ... msbuild {un conjunto completo de parámetros que siguen aquí}} – user20358

+0

@ user20358 Asegúrese de ponerlo en un archivo .proj y llamar a MSBuild con algo como esto: " % windir% \ Microsoft.NET \ Framework \ v4.0.30319 \ MSBuild.exe "/ nologo/verbosity: normal publish.proj% */property: ReleaseTier = estable – Cilvic

8

Este es el código de MSBuild destino donde puedo actualizar todos mis archivos AssemblyInfo.cs (Tienes que init artículos AssemblyInfoFilesToUpdate colecciones antes de usar este objetivo):

<!-- Update all the assembly info files with generated version info --> 
    <Target Name="AfterGet" Condition="'$(ServerBuild)'=='true' And '$(BuildVersion)'!=''"> 
    <Message Text="Modifying AssemblyInfo files..." /> 
    <!-- Clear read-only attributes --> 
    <Attrib Files="@(AssemblyInfoFilesToUpdate)" Normal="true" /> 
    <!-- Update AssemblyVersion --> 
    <FileUpdate Files="@(AssemblyInfoFilesToUpdate)" 
      Regex="AssemblyVersion\(&quot;.*&quot;\)\]" 
      ReplacementText="AssemblyVersion(&quot;$(BuildVersion)&quot;)]" /> 
    <!-- Update AssemblyFileVersion --> 
    <FileUpdate Files="@(AssemblyInfoFilesToUpdate)" 
      Regex="AssemblyFileVersion\(&quot;.*&quot;\)\]" 
      ReplacementText="AssemblyFileVersion(&quot;$(BuildVersion)&quot;)]" /> 
    <Message Text="AssemblyInfo files updated to version &quot;$(BuildVersion)&quot;" /> 
    </Target> 

estoy usando FileUpdate task from MSBuildCommunityTasks.

+0

Alternativamente, puede usar la tarea' FileUpdate' una vez especificando ' Regex' argumento como 'Regex =" (\ d +) \. (\ D +) \. (\ D +) \. (\ D +) "'. –

+0

@DerekW Eso puede tener consecuencias no deseadas. –

+0

@RhysBevilaqua: ¿Podría darnos un ejemplo (uno en el que AssemblyFileVersion y AssemblyVersion sean los mismos)? –

2

Una pregunta bastante antigua con una respuesta aceptada, pero también (debido a limitaciones en el servidor de compilación CI) quería hacer esto a través de un archivo por lotes en lugar de powershell o MS Build Tasks. Esto es lo que se me ocurrió: se supone que el directorio de la solución es el directorio actual:

SetVersion.bate de

@echo off 
setlocal enabledelayedexpansion 

if [%1] == [] GOTO :USAGE 
set version=%1 
set fileversion=%1 
set informationalversion=%1 

if [%2] NEQ [] SET fileversion=%2 
if [%3] NEQ [] SET informationalversion=%3 

echo Setting assembly version information 

for /F "delims=" %%f in ('dir /s /b Assemblyinfo.cs') do (
    echo ^> %%f 

    pushd %%~dpf 

    for /F "usebackq delims=" %%g in ("AssemblyInfo.cs") do (
     set ln=%%g 
     set skip=0 

     if "!ln:AssemblyVersion=!" NEQ "!ln!" set skip=1 
     if "!ln:AssemblyFileVersion=!" NEQ "!ln!" set skip=1 
     if "!ln:AssemblyInformationalVersion=!" NEQ "!ln!" set skip=1 

     if !skip!==0 echo !ln! >> AssemblyInfo.cs.versioned 
    ) 

    echo [assembly: AssemblyVersion^("%version%"^)] >> AssemblyInfo.cs.versioned 
    echo [assembly: AssemblyFileVersion^("%fileversion%"^)] >> AssemblyInfo.cs.versioned 
    echo [assembly: AssemblyInformationalVersion^("%informationalversion%"^)] >> AssemblyInfo.cs.versioned 

    copy /y AssemblyInfo.cs AssemblyInfo.cs.orig 
    move /y AssemblyInfo.cs.versioned AssemblyInfo.cs 

    popd 
) 
echo Done^^! 

GOTO:EOF 

:USAGE 
echo Usage: 
echo. 
echo SetVersion.bat Version [FileVersion] [InformationalVersion] 
echo. 

Explicación

Básicamente esto recursivamente todas las subcarpetas y archivos AssemblyInfo.cs identificar, y luego la línea por línea copiar los archivos a un nuevo archivo. Si se encuentra cualquiera de las entradas de la versión del ensamblaje, se omiten. Luego, al final de cada archivo, agrega los números de versión suministrados.

Para aquellos gurús de lotes, algunos pueden preguntar por qué prefiero usar for /F con dir /s en lugar de for /R para iterar sobre los archivos. Básicamente, es porque creo que el recursivo es un poco torpe ya que se ejecutará para todos los subdirectorios (no solo para los archivos coincidentes) cuando no se proporcionen comodines. El uso del comando dir es más consistente y más fácil de predecir.

Nota: Este archivo por lotes se eliminarán todas las líneas vacías de los archivos AssemblyInfo.cs

+0

wow. muchas gracias. Esto me salvó de mucho trabajo –

Cuestiones relacionadas