2012-07-11 14 views
9

Estoy tratando de hacer que una secuencia de comandos de MSBuild funcione para crear y extraer para su implementación una aplicación web bastante grande. (Estamos hablando de unos miles de archivos en varias docenas de directorios, aquí. Se trata de una base de código heredada heredada, así que no puedo hacer mucho al respecto.) La compilación en sí funciona bien, pero parece que no puedo copiar el archivos a una ubicación de colocación funcionando correctamente.Copiar archivos de salida de compilación, preservar la estructura de directorios, da 'Caracteres no válidos en la ruta'

Aquí hay un fragmento que muestra lo que tengo en la escritura de la estructura:

<PropertyGroup Condition=" '$(UseBuildNumber)' == 'true' "> 
    <ReleaseDirectory>$(ReleaseBaseDirectory)$(ReleaseName)\$(BuildNumber)</ReleaseDirectory> 
</PropertyGroup> 

<ItemGroup> 
    <OutputFiles Include=" 
       $(SourceRoot)**\*.aspx; 
       $(SourceRoot)**\*.dll; 
       $(SourceRoot)**\*.gif; 
       $(SourceRoot)**\*.ascx; 
       " /> 
</ItemGroup> 

<Message Text="Output files ==> @(OutputFiles)" /> 

<Copy 
    SourceFiles="@(OutputFiles)" 
    DestinationFolder="$(ReleaseDirectory)" 
    SkipUnchangedFiles="false" 
    /> 

he puesto unos extra <Message/> allí para verificar que las trayectorias individuales se expanden correctamente, y ambos $(SourceRoot) y $(ReleaseDirectory) sí tienen los caminos correctos. Sin embargo, en la salida, lo entiendo (ruta completa eludido por razones de brevedad):

Task "Message" 
    Output files ==> ...\Requirement1866**\*.aspx;...\Requirement1866**\*.dll;...\Requirement1866**\*.gif;...\Requirement1866**\*.ascx 
Done executing task "Message". 

Obviamente, la expansión de comodines no se ha realizado, y la siguiente Copy entonces (lo suficientemente predecible) falla. Incluyo solo uno; en realidad esto se repite para cada uno de los patrones comodín de nombre de archivo (que a su vez son muchos más de lo que incluí en el fragmento de script de compilación más arriba).

Using "Copy" task from assembly "Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". 
Task "Copy" 
    Copying file from "*basedir*\Requirement1866**\*.aspx" to "*targetdir*\Requirement1866\*buildnumber*\*.aspx". 
    Command: 
    copy /y "*basedir*\Requirement1866**\*.aspx" "*targetdir*\Requirement1866\*buildnumber*\*.aspx" 
d:\Builds\215\BuildType\TFSBuild.proj(120,5): error MSB3021: Unable to copy file "*basedir*\Requirement1866**\*.aspx" to "*targetdir*\Requirement1866\*buildnumber*\*.aspx". Illegal characters in path. 

seguido de:

d:\Builds\215\BuildType\TFSBuild.proj(120,5): error MSB3021: Unable to copy file "*basedir*\Requirement1866**\*.aspx" to "*targetdir*\Requirement1866\*buildnumber*\*.aspx". Illegal characters in path. 

El único éxito razonablemente relevante que he encontrado en mis esfuerzos a googlear esto era Copy Task - Illegal characters in path, pero ya estoy usando un <ItemGroup>, y el ejemplo <CreateItem> (adaptado) no funcionó en absoluto, abortando temprano con un error que decía que TaskParameter era desconocido (lo siento, no tengo el mensaje de error exacto delante de mí).

Como una medida provisional, podría ingresar y copiar manualmente los archivos relevantes desde el directorio de salida de compilación a donde los desee, pero quiero que ese proceso sea automatizado.

¿Cómo, entonces, usando MSBuild, copio los archivos que se crean durante el proceso de compilación en un directorio de salida, mientras se preserva la estructura de directorios relativa, sin enumerarlos uno por uno?

+0

No tengo una respuesta directa, pero he encontrado este problema antes, también. Terminé escribiendo un script de PowerShell para hacerlo y llamándolo como una acción posterior a la construcción. Además, +1 a la pregunta porque está TAN impresionantemente bien investigado. ¡Espero ansioso la respuesta correcta que se publique! – allquixotic

Respuesta

20

Básicamente, ** es una sola trayectoria-elemento y por lo tanto debe ser correspondientemente backslash delimitado en el Include Directiva:

<ItemGroup> 
    <OutputFiles Include=" 
       $(SourceRoot)\**\*.aspx; 
       $(SourceRoot)\**\*.dll; 
       $(SourceRoot)\**\*.gif; 
       $(SourceRoot)\**\*.ascx; 
       " /> 
</ItemGroup> 

Nota la diferencia entre especificar, por ejemplo, $(SourceRoot)\**\*.aspx a diferencia del roto $(SourceRoot)**\*.aspx. Si $(SourceRoot) hubiera finalizado con \, la expansión del comodín probablemente también habría funcionado al principio.

En segundo lugar, en <Copy/>, utilice %(RecursiveDir):

<Copy 
    SourceFiles="@(OutputFiles)" 
    DestinationFolder="$(ReleaseDirectory)\%(RecursiveDir)" 
    SkipUnchangedFiles="false" 
    /> 

Con estos cambios, parece que funciona igual que yo quiero que: los archivos se copian en el directorio de destino previsto, y la estructura de directorios en la fuente se conserva en la ubicación de destino.

2

Otra sugerencia, en lugar de agregar Incluye para cada tipo de archivo, es fácil agregar Excludes.

<ItemGroup> 
    <OutputFiles Include="$(SourceRoot)**\*.*" Exclude="$(SourceRoot)**\*.cs;$(SourceRoot)**\*.resx" " /> 
</ItemGroup> 

De esta manera, la salida incluirá cualquier JS, HTML, DHTML y otros tipos de archivos que sean necesarios.

+0

Cualquiera de los dos enfoques funciona, dependiendo de las necesidades. En mi caso particular, fue significativamente más fácil enumerar lo que quería copiar y simplemente excluir todo lo demás. –

Cuestiones relacionadas