2012-01-24 26 views
41

¿Es posible usar la transformación de documento XML de Microsoft para preparar web.configs fuera de MSBuild? Me gustaría utilizar PowerShell para hacer estas transformaciones sin tener que ejecutar esto a través del motor MSBuild. Si Microsoft hubiera usado XSLT estándar, sería fácil hacerlo en PowerShell. Por lo que puedo decir, tengo que usar sus C: \ Archivos de programa (x86) \ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft.Web.Publishing.Tasks.dll que requieren un motor de compilación. GraciasWeb.Config se transforma fuera de Microsoft MSBuild?

Respuesta

77

Creé una pequeña función para manejar la transformación de documentos XML de Microsoft en PowerShell.

Copié el archivo Microsoft.Web.XmlTransform.dll de la carpeta de compilación de Visual Studio a la ruta de mi script, pero puede consultarlo desde la carpeta de origen si lo desea.

function XmlDocTransform($xml, $xdt) 
{ 
    if (!$xml -or !(Test-Path -path $xml -PathType Leaf)) { 
     throw "File not found. $xml"; 
    } 
    if (!$xdt -or !(Test-Path -path $xdt -PathType Leaf)) { 
     throw "File not found. $xdt"; 
    } 

    $scriptPath = (Get-Variable MyInvocation -Scope 1).Value.InvocationName | split-path -parent 
    Add-Type -LiteralPath "$scriptPath\Microsoft.Web.XmlTransform.dll" 

    $xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument; 
    $xmldoc.PreserveWhitespace = $true 
    $xmldoc.Load($xml); 

    $transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdt); 
    if ($transf.Apply($xmldoc) -eq $false) 
    { 
     throw "Transformation failed." 
    } 
    $xmldoc.Save($xml); 
} 

Transformar web.config utilizando web.release.config:

XmlDocTransform("Web.config", "Web.Release.config") 
+0

Fantástico, eso es exactamente lo que necesitaba para escribir una versión de C# –

+10

Tengo un script autocomprimible de PowerShell que puedes usar en https://gist.github.com/sayedihashimi/f1fdc4bfba74d398ec5b –

+1

¡muy bonito! Tuve que llamar a Resolve-Path en $ xml y $ xdt pero aparte de eso, ¡es muy útil !, thx – PierrOz

10

La lógica de la transformación está contenida dentro de la tarea TransformXml misma. Si desea llamarlo desde el código, deberá usar la API de MSBuild con un motor simulado y ejecutarlo. Tengo un código para esto si quieres.

En su caso, ya que mencionó PowerShell, lo mejor que puede hacer es simplemente crear un archivo MSBuild contenedor para invocar la tarea TransformXml. Digo esto porque PowerShell está configurado para ejecutarse en .NET 2.0, pero la tarea TransformXml requiere .NET 4.0. Para llamarlo desde un archivo ficticio de MSBuild puede consultar mi blog al http://sedodream.com/2010/04/26/ConfigTransformationsOutsideOfWebAppBuilds.aspx, pero también he pegado una muestra de ese enlace a continuación.

<Project ToolsVersion="4.0" DefaultTargets="Demo" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <UsingTask TaskName="TransformXml" 
      AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/> 

    <Target Name="Demo"> 
     <TransformXml Source="app.config" 
         Transform="Transform.xml" 
         Destination="app.prod.config"/> 
    </Target> 
</Project> 
+2

Gracias Sayed, que en realidad fue con su solución. Lo modifiqué un poco para incluir grupos de propiedades para los 3 elementos, así que pude anular aquellos en la línea de comando de PowerShell. Aprendido de su libro :) ' Web.config Web.Debug.config Web.Prod.config \t \t \t \t ' –

4

Doble a la observó el uso de MSDeploy ya que cuenta con las API de secuencias de comandos PowerShell que le permiten transformar y desplegar su paquete.

También puede consultar XML-Document-Transform que, si lo desea, puede escribir su propio código para realizar la Transformación.

Aquí hay un proyecto codeplex que hizo algo similar. XDT Transformation Tool

5

Sobre la base de la respuesta de Michel escribí una función de C# que logre el mismo.

Por supuesto que podría invocar la DLL resultante con PowerShell, pero en realidad estaba buscando una versión totalmente programática, así que aquí está, en caso de que alguien más está en busca de solución similar:

using Microsoft.Web.XmlTransform; 

... 

public static void TransformConfig(string configFileName, string transformFileName) 
{ 
    var document = new XmlTransformableDocument(); 
    document.PreserveWhitespace = true; 
    document.Load(configFileName); 

    var transformation = new XmlTransformation(transformFileName); 
    if (!transformation.Apply(document)) 
    { 
     throw new Exception("Transformation Failed"); 
    } 
    document.Save(configFileName); 
} 

Se hará sólo tiene que incluir una referencia a lo siguiente:

C: \ archivos de programa (x86) \ MSBuild \ Microsoft \ VisualStudio \ v11.0 \ web \ Microsoft.Web.XmlTransform.dll

+0

¡Gran respuesta, esto necesita más votos! – Matt

5

Microsoft ha publicado XDT en codeplex http://xdt.codeplex.com y como paquete NuGet https://www.nuget.org/packages/Microsoft.Web.Xdt/. También he creado un cerdo NuGet con una tarea MSBuild, TransformXml y un .exe para invocarlos https://www.nuget.org/packages/SlowCheetah.Xdt/1.1.6-beta.

Para PowerShell Creé un script de auto-bootstrapping que puede usar https://gist.github.com/sayedihashimi/f1fdc4bfba74d398ec5b.

Más acerca de las secuencias de comandos auto bootstrapping en http://sedodream.com/2014/07/22/StopCheckinginBinariesInsteadCreateSelfbootstrappingScripts.aspx.

1

He actualizado el script un poco para que funcione con la última versión de powershell y lo haga un poco más fácil.

function XmlDocTransform($xml, $xdt) 
{ 
     $scriptpath = $PSScriptRoot + "\" 
     $xmlpath = $scriptpath + $xml 
     $xdtpath = $scriptpath + $xdt 

     if (!($xmlpath) -or !(Test-Path -path ($xmlpath) -PathType Leaf)) { 
     throw "Base file not found. $xmlpath"; 
     } 

     if (!($xdtpath) -or !(Test-Path -path ($xdtpath) -PathType Leaf)) { 
     throw "Transform file not found. $xdtpath"; 
     } 

     Add-Type -LiteralPath "$PSScriptRoot\Microsoft.Web.XmlTransform.dll" 

     $xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument; 
     $xmldoc.PreserveWhitespace = $true 
     $xmldoc.Load($xmlpath); 

     $transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdtpath); 
     if ($transf.Apply($xmldoc) -eq $false) 
     { 
      throw "Transformation failed." 
     } 
     $xmldoc.Save($xmlpath); 

     Write-Host "Transformation succeeded" -ForegroundColor Green 
    } 

Y para invocar la función de uso

XmlDocTransform "App.config" "App.acc.config" 
Cuestiones relacionadas