我曾经写过一篇文章 如何创建一个基于命令行工具的跨平台的 NuGet 工具包,通过编写一个控制台程序来参与编译过程。但是,相比于 基于 Task 的方式,可控制的因素还是太少了。

有没有什么办法能够让控制台程序也能与 MSBuild Target 之间发生更多的信息交换呢?答案是有的,通过捕获控制台的输出!


 

捕获控制台输出

如果你喜爱阅读文档,那么答案已经不陌生了,在微软的官方文档 Exec Task 中就已经提及了属性 ConsoleToMSBuild。将此属性设置为 True,将能够捕获控制台输出到 MSBuild 中。(不过据说典型的程序员是不爱看文档的

那么,捕获的输出去了哪里呢?

我在 如何创建一个基于 MSBuild Task 的跨平台的 NuGet 工具包 中提到了使用 Output 来将 Task 中的参数输出出来。而 Exec 也是这么做的。我们将 ConsoleOutput 输出出来即可。由于这个属性不是 ITaskItem[] 类型的,所以我们只能得到字符串属性,于是只能通过 PropertyName 来接收这样的输出。

<Exec ConsoleToMSBuild="True" Command="&quot;$(NuGetWalterlvToolPath)&quot;">
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfTheCommand" />
</Exec>

PropertyGroup 转 ItemGroup

如果你需要的只是一个字符串,那看完上一节就已经够了。但如果你希望得到的是一组值(例如新增了一组需要编译的文件),那么需要得到的是 ItemGroup 中的多个值,而不是 PropertyGroup 中的单个值。(如果不太明白 ItemGroupPropertyGroup 之间的差别,不要紧,可以阅读 理解 C# 项目 csproj 文件格式的本质和编译流程。)

MSBuild 还自带了一个 Task,名为 CreateItem,就是从一段字符串创建一组 Item。通过下面这段代码,我们能将上一节捕获到的属性转换成项的集合。

<CreateItem Include="$(OutputOfTheCommand)">
<Output TaskParameter="Include" ItemName="AdditionalCompile" />
</CreateItem>

这样,我们便能够

更加完整的代码可能更具有参考意义,所以我贴在了下面:

<Project>
<Target Name="GenerateAdditionalCode" BeforeTargets="CoreCompile">
<Exec ConsoleToMSBuild="True" Command="&quot;$(NuGetWalterlvToolPath)&quot;">
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfTheCommand" />
</Exec>
</Target>
<Target Name="_IncludeGeneratedAdditionalCode" AfterTargets="GenerateAdditionalCode">
<CreateItem Include="$(OutputOfTheCommand)">
<Output TaskParameter="Include" ItemName="AdditionalCompile" />
</CreateItem>
<ItemGroup>
<Compile Include="@(AdditionalCompile)" />
</ItemGroup>
<Message Text="额外添加的编译文件:@(AdditionalCompile)" />
</Target>
</Project>

CreateItem 的转换分隔符

CreateItem 从属性或字符串转到项是根据分隔符来区分的。由于使用 @(Item) 来获取项时,会得到一个用 ; 分隔的字符串,所以不难想到我们控制台输出的字符串使用 ; 分隔即能满足我们的转换需求。但事实上这是不行的!

因为控制台的转换,每行是有缓冲区限制的,也就是说单行字数不能过多,否则会自动加换行符——这可能导致我们转换成的某一项或者多项中间带了换行符,从而导致错误。

于是,建议直接在控制台程序中使用换行符本身作为分隔符,这样便可以去除这样的限制。因为 CreateItem 也是支持换行符分隔的。


参考资料

如何使用 MSBuild Target(Exec)中的控制台输出的更多相关文章

  1. log4j中Spring控制台输出Debug级信息过多解决方法

    log4j中Spring控制台输出Debug级信息过多解决方法 >>>>>>>>>>>>>>>>> ...

  2. Qt在VS2013或Qt Creator 中的控制台输出方式设置

    首先值得注意的是:在写程序的时候,项目保存路径不要涉及到中文,否则容易出错! 一.Qt在VS2013中的控制台输出方式: 注意:这里是而不是Qt Application. 然后直接点击finish即可 ...

  3. java项目中eclipse控制台输出log4j的信息

    最近做的一个hadoop项目中,用MR实现了一个比较复杂的问题,其中的日志信息都是使用的是log4j来处理的.但不知怎么控制台不输出日志信息,只能输出System.out.println()信息,这个 ...

  4. MFC中添加控制台输出

    可以在CWinApp的InitInstance()中调用下面的函数,以生成控制台: #include <io.h> #include <fcntl.h> void InitCo ...

  5. 如何在 MSBuild Target(Exec)中报告编译错误和编译警告

    编译错误和编译警告 MSBuild 的 Exec 自带有错误和警告的标准格式,按照此格式输出,将被识别为编译错误和编译警告. 而格式只是简简单单的 error: 开头或者 warning: 开头.冒号 ...

  6. Java中从控制台输入数据的几种常用方法

    Java中从控制台输入数据的几种常用方法 一.使用标准输入串System.in //System.in.read()一次只读入一个字节数据,而我们通常要取得一个字符串或一组数字 //System.in ...

  7. 将source类中的属性值赋给target类中对应的属性

    /** * 对象的属性值拷贝 * <p> * 将source对象中的属性值赋值到target对象中的属性,属性名一样,类型一样 * <p> * example: * <p ...

  8. Myeclipse和 eclipse中的控制台汉字横着显示修改

    Myeclipse和 eclipse中的控制台汉字横着显示问题的修改 如图: 同一种字体有两种显示方式,比如微软雅黑和@微软雅黑,前一种汉字是竖着显示,后一种汉字是横着显示. 修改方法: prefer ...

  9. ASP.NET Core 集成测试中通过 Serilog 向控制台输出日志

    日志是程序员的雷达,不仅在生产环境中需要,在集成测试环境中也需要,可以在持续集成失败后帮助定位问题.与生产环境不同,在集成测试环境中使用控制台输出日志更方便,这样可以通过持续集成 runner 执行 ...

随机推荐

  1. Unique Binary Search Trees,Unique Binary Search Trees2 生成二叉排序树

    Unique Binary Search Trees:求生成二叉排序树的个数. Given n, how many structurally unique BST's (binary search t ...

  2. Dive into Spring framework -- 了解基本原理(一)

    在继续我们的分析之前,推荐各位静心来读一下<<Expert_OneOne_J2EE_Design_and_Development>> 第四章, 正如spring BeanFac ...

  3. jmeter-对响应数据进行unicode转码

    1,请求接口成功后,返回数据为unicode编码,查看不方便

  4. 分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型

    分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型   分布式缓存特性: 1) 高性能:当传统数据库面临大规模 ...

  5. dva-loading使用方法

    1. 下载dva-loading npm install dva-loading --save 2. 导入并使用dva-loading import createLoading from 'dva-l ...

  6. ie下的bug之button

    场景描述: 现在页面设计是都喜欢自定义按钮样式,某日接收到页面发现在ie下有bug,上代码: <div> <button><span><a href=&quo ...

  7. $.ajaxComplete()

    https://www.cnblogs.com/RachelChen/p/5433881.html 全局ajax事件   必须当页面上存在任何ajax请求的时候都将触发这些特定的全局ajax处理函数. ...

  8. js获取显示器、页面等高度 (转)

    网页可见区域宽:document.body.clientWidth网页可见区域高:document.body.clientHeight网页可见区域宽:document.body.offsetWidth ...

  9. OpenMP学习

    当数据量较大或者时间复杂度高的时候,盲目地等待结果,开发效率极低. 听说OpenMP可以多核并行运算,加快运行速度.整理了一些OpenMP的资料,以待学习. 1.openMP的一点使用经验 2.Ope ...

  10. LeetCode OJ:Burst Balloons(击破气球)

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...