Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get an msbuild task to do config transforms on a collection of files?

I am trying to transform all of the web.config files in a project I have, here's a my tree structure:

  • Transform.bat
  • Transforms
    • ConfigTransform.proj
    • Web.Transform.config
  • Website
    • web.config
    • Views
      • web.config

There's more web.config files, but the idea is that this will find all of them and apply the same config transform on them.

I've taken a few hints from a blog post I found but I get stuck in the last step, the actual transformation. Also there's a bit of a rough part in the middle that I don't really like (I don't quite understand what I'm doing and I'm obviously doing it wrong). Here's where I am so far:

<Project ToolsVersion="4.0" DefaultTargets="Transform" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask TaskName="TransformXml" AssemblyFile="Tools\Microsoft.Web.Publishing.Tasks.dll"/>

    <PropertyGroup>
        <SitePath>..\..\Website</SitePath>
        <WebConfigTransformInputFile>$(SitePath)\Web.config</WebConfigTransformInputFile>
        <WebConfigTransformFile>Web.Transform.config</WebConfigTransformFile>
        <OutDir>..\N\N\</OutDir>

    </PropertyGroup>

    <ItemGroup>
        <_FilesToTransform Include="$(SitePath)\**\web.config"/>
    </ItemGroup>

    <Target Name="Transform">

    <MakeDir Directories="@(_FilesToTransform->'$(OutDir)%(RelativeDir)')" />

    <TransformXml Source="@(_FilesToTransform->'$(OutDir)%(RelativeDir)%(Filename)%(Extension)')"
                  Transform="$(WebConfigTransformFile)"
                  Destination="@(_FilesToTransform->'$(OutDir)%(RelativeDir)%(Filename)%(Extension)')" />
    </Target>
</Project>

My Transform.bat looks like this:

%systemroot%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe %CD%\Transforms\ConfigTransform.proj

So when I call the batch, the appropriate directories get created. However, as you can see I've had to be a little creative with the OutDir, making it ..\N\N. For some reason, if I don't do this the OutDir path will be exactly the same as the input directory. So I obviously need to change something in MakeDir but I'm not sure what.

The real problem comes when it starts to do the transforms. I've tried to keep the TransformXml Source parameter like this or like so:

@(_FilesToTransformNotAppConfig->'%(FullPath)')

The latter gives me an error "Could not open Source file: The given path's format is not supported." and the former gives me this output:

Build started 30-4-2012 14:02:48.
Project "D:\Dev\transform\DoTransforms\Transforms\ConfigTransform.proj" on node 1 (default targets).
Transform:
  Creating directory "..\N\N\..\..\Website\Views\".
  Transforming Source File: ..\N\N\..\..\Website\Views\Web.config;..\N\N\..\..\Website\Web.config
D:\Dev\transform\DoTransforms\Transforms\ConfigTransform.proj(32,2): error : Could not open Source file: Could not find a part of the path 'D:\Dev\transform\DoTransforms\Website\Views\Web.config;\Website\Web.config'.
  Transformation failed
Done Building Project "D:\Dev\transform\DoTransforms\Transforms\ConfigTransform.proj" (default targets) -- FAILED.

Build FAILED.

To summarize my questions:

  1. How do I avoid the path issue for the OutDir? I've fiddled with multiple paths but I can't get it right.
  2. How do I get the TransformXml task to accept multiple files in the Source attribute?
like image 226
sebastiaan Avatar asked Apr 30 '12 12:04

sebastiaan


People also ask

How add config transform?

If you have a web application project, Right-click on web. config and choose Add Config Transform. This will add any config transforms that are missing from your project based on build configurations (i.e. if you have Production and Staging build configs, both will get a transform added).

What is a config transform?

A Web. config transformation file contains XML markup that specifies how to change the Web. config file when it is deployed. You can specify different changes for specific build configurations and for specific publish profiles.

What is XDT transform?

XDT is a simple and straight forward method of transforming the web. config during publishing/packaging. Transformation actions are specified using XML attributes defined in the XML-Document-Transform namespace, that is mapped to the xdt prefix.

Where is web config file in Visual Studio 2022?

config file is located in the %SystemRoot%\Microsoft.NET\Framework\%VersionNumber%\CONFIG\ folder. The default settings that are contained in the Machine.


1 Answers

I think you were pretty close. I have pasted a sample below which shows how to do this.

In my sample I discover the transform sitting next to the web.config file itself. For your scenario you can just use an MSBuild property pointing to a specific file.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="TransformAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>

  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)'=='' ">Release</Configuration>
    <OutputFolder Condition=" '$(OutputFolder)'=='' ">C:\temp\transformed-files\</OutputFolder>
  </PropertyGroup>

  <!--
  This target shows how to transform web.config with a specific transform file associated to that specific web.config file.
  -->
  <Target Name="TransformAll">

    <!-- discover the files to transform -->
    <ItemGroup>
      <FilesToTransofm Include="$(MSBuildProjectDirectory)\**\web.config"/>
    </ItemGroup>

    <!-- Ensure all target directories exist -->
    <MakeDir Directories="@(FilesToTransofm->'$(OutputFolder)%(RecursiveDir)')"/>

    <!-- TransformXml only supports single values for source/transform/destination so use %(FilesToTransofm.Identity)
         to sned only 1 value to it -->
    <TransformXml Source="%(FilesToTransofm.Identity)"
                  Transform="@(FilesToTransofm->'%(RecursiveDir)web.$(Configuration).config')"
                  Destination="@(FilesToTransofm->'$(OutputFolder)%(RecursiveDir)web.config')" />    
  </Target>

</Project>

FYI you can download a full sample at https://github.com/sayedihashimi/sayed-samples/tree/master/TransformMultipleWebConfigs.

like image 100
Sayed Ibrahim Hashimi Avatar answered Sep 23 '22 00:09

Sayed Ibrahim Hashimi