Question

I'm trying to transform web.configs as part of a build process through MSBuild, which is fine; but dealing with multiple web.configs in the same solution is causing problems.

The code we are using at the moment extracts web.config specific information and passes it to a transform target, both of these operations are bundled in a DependsOnTargets target:

<Target Name="ExtractWebConfigParams_1">
  <!-- Get webConfig1 info -->
</Target>

<Target Name="TransformWebConfig_1">
  <TransformXml Source="%(webConfig1).Web.config"
                Transform="%(webConfig1).Web.Stage.config"
                Destination="%(webConfig1).Web.config"
                StackTrace="$(StackTraceEnabled)" />
</Target>

<Target Name="ExtractWebConfigParams_2">
  <!-- Get webConfig2 info -->
</Target>

<Target Name="TransformWebConfig_2">
  <TransformXml Source="%(webConfig2).Web.config"
                Transform="%(webConfig2).Web.Stage.config"
                Destination="(webConfig2).Web.config"
                StackTrace="$(StackTraceEnabled)" />
</Target>

<Target
    Name="Transform_1"
    DependsOnTargets="ExtractWebConfigParams_1;                                                                                                     
                      TransformWebConfig_1;">
</Target>   

<Target
    Name="Transform_2"
    DependsOnTargets="ExtractWebConfigParams_2;                                                                                                     
                      TransformWebConfig_2;">
</Target>   

Our solution may contain up to 5 different web.configs, so there would have to be an extract, transform and DependsOnTargets target for every one of them.

I can't see a way of getting around using multiple extract targets but does anyone know if there's a way to call the transform target with different parameters instead of making an entirely new target everytime?

Was it helpful?

Solution

You can write a separate .msbuild (.proj) file as "reusable logic".

I have a "zip up website" common logic I'll post below. My example was about zipping up an asp.net website, but encapsulating the rules about which files to ignore (.csproj for example).......and also have a few "hooks" for ignoring some files. Like the "images" directory, ours was HUGE, so I didn't want to zip that up every time.

My example is not directly related to your need. Its the idea that is important. Encapsulate all your logic into one file, and pass parameters to it.

I include the .proj file in the Main.proj file. Then pass parameters to it.

ONE CAVEAT. Relative directories do NOT work in the sub .proj file if it is located anywhere besides the same directory as the Main.proj file.
Ala, you cannot set a directory property to something like ".\bin\", you have to figure out the full path BEFORE you call the sub-proj file and pass the full folder name. Is this example, "c:\myfolder\mysolution\myproject1\bin" ... aka, whatever f

Code to put in the "outside" Main.proj file:

  <Target Name="ZipItUpUsingCommonLogic">

    <Message Text="    " />
    <Message Text=" About to Call External MSBUILD File " />
    <Message Text="    " />

    <MSBuild Projects="..\..\CommonLogicMsBuildStuff\WebSiteZippingCommonLogic.proj" Targets="WebSiteZippingAllTargetsWrapper" Properties="WebSiteFolderFullPath=c:\workstuff\mywebsolution;OutputFolderFullPath=c:\workstuff\buildoutputs;WebSiteZipFileNameNonConfig=MyNonConfigFiles$(Configuration).zip;WebSiteZipFileNameConfigFiles=MyWebSiteConfigFiles$(Configuration).zip;RevisionNumber=333;IgnoreFolder1=c:\workstuff\mywebsolution\images" />

</Target>

Code for a file named "WebSiteZippingCommonLogic.proj":

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

  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
  <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks" />
  <!-- There was an issue with the xsl/document(path) function......this help address the issue.  -->

    <Target Name="WebSiteZippingAllTargetsWrapper">
        <CallTarget Targets="ShowParameters" />
        <CallTarget Targets="ValidateParameters" />
        <CallTarget Targets="ZipTheWebSite" />
  </Target>

  <Target Name="ValidateParameters">
    <Error Text="The WebSiteFolderFullPath property was not passed in correctly." Condition="'$(WebSiteFolderFullPath)' == ''" />
    <Error Text="The OutputFolderFullPath property was not passed in correctly." Condition="'$(OutputFolderFullPath)' == ''" />
    <Error Text="The WebSiteZipFileNameNonConfig property was not passed in correctly." Condition="'$(WebSiteZipFileNameNonConfig)' == ''" />
    <Error Text="The WebSiteZipFileNameConfigFiles property was not passed in correctly." Condition="'$(WebSiteZipFileNameConfigFiles)' == ''" />
    <!--<Error Text="The RevisionNumber property was not passed in correctly." Condition="'$(RevisionNumber)' == ''" />-->
  </Target>

    <Target Name="ShowParameters">

        <Message Text=" WebSiteFolderFullPath = $(WebSiteFolderFullPath)" />
        <Message Text=" OutputFolderFullPath = $(OutputFolderFullPath)" />
        <Message Text=" WebSiteZipFileNameNonConfig = $(WebSiteZipFileNameNonConfig)" />
        <Message Text=" WebSiteZipFileNameConfigFiles = $(WebSiteZipFileNameConfigFiles)" />
        <Message Text=" IgnoreFolder1 = $(IgnoreFolder1)" />
        <Message Text=" IgnoreFolder2 = $(IgnoreFolder2)" />
        <Message Text=" IgnoreFolder3 = $(IgnoreFolder3)" />
        <Message Text="    " />
        <Message Text="    " />
      </Target>


    <Target Name="ZipTheWebSite" DependsOnTargets="ValidateParameters">

        <ItemGroup>
            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.sln" />
            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.vbproj" />
            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.csproj" />

            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\*.config" />


            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\.svn\**\*.*" />
            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\obj\**\*.*" />

            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)\**\.svn\**" />
            <WebSiteExcludeFiles Include="$(WebSiteFolderFullPath)**\.svn\**\*.*" />

            <WebSiteExcludeFiles Include="$(IgnoreFolder1)\**\*.*" Condition="'$(IgnoreFolder1)' != ''" />
            <WebSiteExcludeFiles Include="$(IgnoreFolder2)\**\*.*" Condition="'$(IgnoreFolder2)' != ''" />          
            <WebSiteExcludeFiles Include="$(IgnoreFolder3)\**\*.*" Condition="'$(IgnoreFolder3)' != ''" />              

        </ItemGroup>

        <ItemGroup>
            <WebSiteNonConfigIncludeFiles Include="$(WebSiteFolderFullPath)\**\*.*" Exclude="@(WebSiteExcludeFiles)">
            </WebSiteNonConfigIncludeFiles>
        </ItemGroup>


        <MSBuild.Community.Tasks.Zip Files="@(WebSiteNonConfigIncludeFiles)" ZipFileName="$(OutputFolderFullPath)\$(WebSiteZipFileNameNonConfig)" WorkingDirectory="$(WebSiteFolderFullPath)\" />

        <ItemGroup>
            <WebSiteConfigIncludeFiles Include="$(WebSiteFolderFullPath)\**\*.config">
            </WebSiteConfigIncludeFiles>
        </ItemGroup>

        <MSBuild.Community.Tasks.Zip Files="@(WebSiteConfigIncludeFiles)" ZipFileName="$(OutputFolderFullPath)\$(WebSiteZipFileNameConfigFiles)" WorkingDirectory="$(WebSiteFolderFullPath)\" />

        <Message Text="    " />
        <Message Text="    " />

    </Target>


</Project>

If you don't want to encapsulate rules into a separate file, then you may be looking for this:

http://sstjean.blogspot.com/2006/09/how-to-get-msbuild-to-run-complete.html

However, I find the constant "condition-checks" annoying, which is why I went to the "by file" method, which I describe above.

I'm going to copy/paste his example here, just in case his blog ever goes down. Remember "gotdotnet.com" ??

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

  <ItemGroup>
    <Package Include="CommonWebSetup.ism">
      <PackagerType>IS</PackagerType>
      <SetupProjFolder>CommonWebSetup</SetupProjFolder>
      <ISProductConfig>Server</ISProductConfig>
      <ISReleaseConfig>Release</ISReleaseConfig>
    </Package>
    <Package Include="CommonClientSetup.vdproj">
      <PackagerType>VS</PackagerType>
      <SetupProjFolder>CommonClientSetup</SetupProjFolder>
      <ISProductConfig>Client</ISProductConfig>
      <ISReleaseConfig>Release</ISReleaseConfig>
    </Package>
  </ItemGroup>


<Target Name="Test" Outputs="%(Package.Identity)" >
    <Message Text="Removing read-only flag for %(Package.Identity)" Importance="High" />  

    <Message Text="Setting Environment variable for %(Package.Identity)" Importance="High" />  

    <Message Condition=" '%(Package.PackagerType)' == 'IS' " 
             Text="Running InstallShield for %(Package.Identity)" Importance="High" />  

    <Message Condition=" '%(Package.PackagerType)' == 'VS' " 
             Text="Running DevEnv.exe for %(Package.Identity)" Importance="High" />  
</Target>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top