deploymentmsbuildmsbuild-taskmsbuildcommunitytasks

MSBuild ReadLinesFromFile all text on one line


When I do a ReadLinesFromFile on a file in MSBUILD and go to output that file again, I get all the text on one line. All the Carriage returns and LineFeeds are stripped out.

<Project DefaultTargets = "Deploy"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<Import  Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>

<ItemGroup>
    <MyTextFile Include="$(ReleaseNotesDir)$(NewBuildNumber).txt"/>
</ItemGroup>

<Target Name="ReadReleaseNotes">
    <ReadLinesFromFile
        File="@(MyTextFile)" >
        <Output
            TaskParameter="Lines"
            ItemName="ReleaseNoteItems"/>
    </ReadLinesFromFile>
</Target>

<Target Name="MailUsers" DependsOnTargets="ReadReleaseNotes" >
    <Mail SmtpServer="$(MailServer)"
        To="$(MyEMail)"
        From="$(MyEMail)"
        Subject="Test Mail Task"
        Body="@(ReleaseNoteItems)" />
</Target>
<Target Name="Deploy">
    <CallTarget Targets="MailUsers" />
</Target>

</Project>

I get the text from the file which normally looks like this

- New Deployment Tool for BLAH

- Random other stuff()""

Coming out like this

- New Deployment Tool for BLAH;- Random other stuff()""

I know that the code for ReadLinesFromFile will pull the data in one line at a time and strip out the carriage returns.

Is there a way to put them back in? So my e-mail looks all nicely formatted?

Thanks


Solution

  • The problem here is you are using the ReadLinesFromFile task in a manner it wasn't intended.

    ReadLinesFromFile Task
    Reads a list of items from a text file.

    So it's not just reading all the text from a file, it's reading individual items from a file and returning an item group of ITaskItems. Whenever you output a list of items using the @() syntax you will get a separated list, the default of which is a semicolon. This example illustrates this behavior:

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build"    xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    
        <ItemGroup>
            <Color Include="Red" />
            <Color Include="Blue" />
            <Color Include="Green" />
    </ItemGroup>
    
    <Target Name="Build">
            <Message Text="ItemGroup Color: @(Color)" />
    </Target>
    
    </Project>
    

    And the output looks like this:

      ItemGroup Color: Red;Blue;Green
    

    So while the best solution to your problem is to write an MSBuild task that reads a file into a property as a string an not a list of items, that's really not what you asked for. You asked if there was a way to put them back, and there is using MSBuild Transforms.

    Transforms are used to create one list from another and also have the ability to transform using a custom separator. So the answer is to transform your list read in using ReadItemsFromFile into another list with newlines. Here is an example that does just that:

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    
        <ItemGroup>
            <File Include="$(MSBuildProjectDirectory)\Test.txt" />
        </ItemGroup>
    
        <Target Name="Build">
            <ReadLinesFromFile File="@(File)">
                <Output TaskParameter="Lines" ItemName="FileContents" />
            </ReadLinesFromFile>
    
            <Message Text="FileContents: @(FileContents)" />
            <Message Text="FileContents Transformed: @(FileContents->'%(Identity)', '%0a%0d')" />
        </Target>
    
    </Project>
    

    Test.text looks like:

    Red
    Green
    Blue
    

    And the output looks like this:

    [C:\temp]:: msbuild test.proj
    Microsoft (R) Build Engine Version 3.5.21022.8
    [Microsoft .NET Framework, Version 2.0.50727.1433]
    Copyright (C) Microsoft Corporation 2007. All rights reserved.
    
    Build started 11/8/2008 8:16:59 AM.
    Project "C:\temp\test.proj" on node 0 (default targets).
      FileContents: Red;Green;Blue
      FileContents Transformed: Red
    Green
    Blue
    Done Building Project "C:\temp\test.proj" (default targets).
    
    
    Build succeeded.
        0 Warning(s)
        0 Error(s)
    
    Time Elapsed 00:00:00.03
    

    What's going on here is two things.

    @(FileContents->'%(Identity)', '%0a%0d')