问题描述
当我对 MSBUILD 中的文件执行 ReadLinesFromFile 并再次输出该文件时,我将所有文本放在一行上.所有的回车和 LineFeed 都被去掉了.
我从通常看起来像这样的文件中获取文本
- BLAH 的新部署工具- 随机其他东西()"
这样出来
- BLAH 的新部署工具;- 随机其他东西()""
我知道 ReadLinesFromFile 的代码会一次提取一行数据并去掉回车.
有没有办法把它们放回去?所以我的电子邮件看起来格式都很好?
谢谢
这里的问题是您以非预期的方式使用 ReadLinesFromFile
任务.
ReadLinesFromFile 任务
从文本文件中读取 items 列表.
所以它不只是从文件中读取所有文本,而是从文件中读取单个项目并返回 ITaskItem 的项目组.每当您使用 @()
语法输出项目列表时,您将获得一个分隔列表,默认为分号.这个例子说明了这种行为:
<?xml version="1.0" encoding="utf-8"?><Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"><项目组><颜色包括=红色"/><颜色包括=蓝色"/><颜色包括=绿色"/></项目组><目标名称="构建"><Message Text="ItemGroup 颜色:@(Color)"/></目标></项目>
输出如下所示:
ItemGroup 颜色:Red;Blue;Green
因此,虽然解决问题的最佳方法是编写一个 MSBuild 任务,将文件作为字符串而不是项目列表读取到 property 中,但这确实不是您所要求的.您问是否有方式可以将它们放回去,并且正在使用 MSBuild 转换.
转换用于从另一个列表创建一个列表,并且还可以使用自定义分隔符进行转换.因此,答案是将使用 ReadItemsFromFile
读取的列表转换为另一个带有换行符的列表.下面是一个例子:
<?xml version="1.0" encoding="utf-8"?><Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"><项目组><文件包含="$(MSBuildProjectDirectory)Test.txt"/></项目组><目标名称="构建"><ReadLinesFromFile File="@(File)"><输出TaskParameter="Lines" ItemName="FileContents"/></ReadLinesFromFile><Message Text="FileContents:@(FileContents)"/><Message Text="文件内容已转换:@(FileContents->'%(Identity)', '%0a%0d')"/></目标></项目>
Test.text 看起来像:
红色绿蓝色
输出如下所示:
[C: emp]:: msbuild test.projMicrosoft (R) Build Engine 版本 3.5.21022.8[Microsoft .NET 框架,版本 2.0.50727.1433]版权所有 (C) Microsoft Corporation 2007.保留所有权利.构建开始于 2008 年 11 月 8 日上午 8:16:59.节点 0 上的项目C: emp est.proj"(默认目标).文件内容:红色;绿色;蓝色转换后的文件内容:红色绿蓝色完成构建项目C: emp est.proj"(默认目标).构建成功.0 个警告0 错误经过时间 00:00:00.03
这里发生了两件事.
@(FileContents->'%(Identity)', '%0a%0d')
- 我们使用相同的值 (
Identity
) 将列表从一种类型转换为另一种类型,但使用自定义分隔符'%0a%0d'
- 我们正在使用 MSBuild Escaping 来转义换行符(
%0a
) 和回车 (%0d
)
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)MSBuildCommunityTasksMSBuild.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
Coming out like this
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
The problem here is you are using the ReadLinesFromFile
task in a manner it wasn't intended.
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: emp]:: 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: emp est.proj" on node 0 (default targets).
FileContents: Red;Green;Blue
FileContents Transformed: Red
Green
Blue
Done Building Project "C: emp est.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')
- We are transforming the list from one type to another using the same values (
Identity
) but a custom separator'%0a%0d'
- We are using MSBuild Escaping to escape the line feed (
%0a
) and carriage return (%0d
)
这篇关于MSBuild ReadLinesFromFile 一行中的所有文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!