MSBuild ReadLinesFromFile将所有文本读入一行

18

我在MSBUILD中对文件执行ReadLinesFromFile操作后,再次输出该文件时,所有的文本都在一行上。所有的回车符和换行符都被剥离了。

<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>

我从文件中获取文本,通常看起来是这样的

- New Deployment Tool for BLAH

- Random other stuff()""

这样发布

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

我知道ReadLinesFromFile的代码一次从文件中读取一行数据并剥离掉回车符。

有没有办法把回车符放回去?这样我的电子邮件看起来就会格式化得很漂亮了吗?

谢谢

4个回答

45

问题在于您正在以不符合其预期的方式使用 ReadLinesFromFile 任务。

ReadLinesFromFile任务
从文本文件中读取项目列表。

因此,它不仅仅是从文件中读取所有的文本,而是从文件中读取单个项目并返回一个ITaskItems条目组。每当您使用@()语法输出项目列表时,您将获得一个分隔的列表,默认为分号。以下示例说明了此行为:

<?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>

输出结果如下:

  ItemGroup Color: Red;Blue;Green

因此,虽然解决问题的最佳方法是编写一个 MSBuild 任务,将文件读入一个 属性 中作为字符串而不是项目列表,但这并不是你所要求的。你问的是有没有一种方法可以把它们放回去,使用MSBuild 转换就可以实现。

转换用于从一个列表创建另一个列表,并且具有使用自定义分隔符进行转换的能力。因此,答案是将使用 ReadItemsFromFile 读取的列表转换为带有换行符的另一个列表。以下是一个实现这一点的示例:

<?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>

测试文本如下:

Red
Green
Blue

输出结果如下:

[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

这里发生了两件事情。

@(FileContents->'%(Identity)', '%0a%0d')   
  • 我们正在使用相同的值(Identity)但自定义分隔符'%0a%0d'将列表从一种类型转换为另一种类型
  • 我们正在使用MSBuild转义来转义换行符(%0a)和回车符(%0d

2
这正是我在寻找的,谢谢伙计!!我知道我可以编写自定义任务来完成它,但如果我可以使用手头的语法完成它,我宁愿不要在各个地方都有一堆自定义任务。再次感谢!! :-) - evilhomer

43

如果您正在使用 MSBuild 4.0,您可以执行以下操作来获取文件的内容:

$([System.IO.File]::ReadAllText($FilePath))

5
太棒了!如果想要了解在 MSBuild 中允许使用的 .NET 其他有用的内容,请参阅 http://blogs.msdn.com/b/visualstudio/archive/2010/04/02/msbuild-property-functions.aspx。 - Mike
1
这是工作链接:https://devblogs.microsoft.com/visualstudio/msbuild-property-functions/ - Jan

4

我认为你可以使用@(FileContents, '%0a%0d')代替@(FileContents->'%(Identity)', '%0a%0d')


1
你可以使用WriteLinesToFile与

组合。
$([System.IO.File]::ReadAllText($(SourceFilePath))):

< WriteLinesToFile File="$(DestinationFilePath)"  Lines="$([System.IO.File]::ReadAllText($(SourceFilePath)))"
                      Overwrite="true" 
                      />

这将完全复制您的文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接