浅谈VS编译自定义编译任务—MSBuild Task(csproject)

简介:

  在上一篇浅谈.NET编译时注入(C#-->IL)中我们简单的反编译查看了几种c#语法糖和PostSharp在编译成IL时为我做的MSIL注入。紧接着在这节,要来看的就是MSBuild Task。在我们的代码预编译过程中我们可以创建我们自己的任务Task。下面我们就开始做一个简单的Task。

1:首先需要添加Microsoft.Build.Utilities.v3.5.dll和Microsoft.Build.Framework.dll中引用。在Microsoft.Build.Framework中为我们定义了接口ITask,自定义任务需要去实现这个契约。其定义如下: 


 
 
  1. public interface ITask   
  2.     {   
  3.        IBuildEngine BuildEngine { get; set; }   
  4.        ITaskHost HostObject { get; set; }   
  5.        bool Execute();   
  6.     } 

IBuildEngine 从字义上说是编译引擎,他主要承载了我们的编译生成时的信息和消息,警告,错误等事件注册。而Execute这是我们Task执行体。HostObject 任务关联宿主信息。

在Microsoft.Build.Utilities下Task为我们实现了基本的ITask信息。我们可以从这里继承开始。

下面是一个简单的实现:


 
 
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Linq;   
  4. using System.Text;   
  5.  
  6. namespace FirstBuildTask   
  7. {   
  8.     public class MyBuildTask : Microsoft.Build.Utilities.Task   
  9.     {   
  10.         private string outputFile;   
  11.  
  12.         [Microsoft.Build.Framework.Required]   
  13.         public string OutputFile   
  14.         {   
  15.             get { return outputFile; }   
  16.             set { outputFile = value; }   
  17.         }   
  18.  
  19.         public override bool Execute()   
  20.         {   
  21.             Log.LogWarning("test message:" + this.outputFile);   
  22.             return true;   
  23.         }   
  24.     }   

下面我们需要关联Task,本人不喜欢污染,所以加到csproject(也可全局所有项目使用)。

下面我们创建一个简单的控制台


 
 
  1. 程序  
  2.  
  3. using System;   
  4. using System.Collections.Generic;   
  5. using System.Linq;   
  6. using System.Text;   
  7.  
  8. namespace BlogSample   
  9. {   
  10.     class Program   
  11.     {   
  12.         static void Main(string[] args)   
  13.         {   
  14.             Console.WriteLine("ok");   
  15.             Console.Read();   
  16.         }   
  17.     }   

用记事本形式打开csproject文件:

添加我们的Task声明和任务。(xml标记含义将在后续,这里先看看效果。)

声明Task:

< UsingTask  TaskName ="MyBuildTask"  AssemblyFile ="XXXX\bin\Debug\FirstBuildTask1.dll" />

添加任务:

< Target  Name ="AfterBuild" >  
< MyBuildTask  OutputFile ="$(MSBuildProjectFullPath)" />  
  
</ Target >

修改后的csproject文件形如:

上边红线注释的就是我们的Task所做的警告和输出路径的提示。

我们已经完成了一个简单Task,但还遗留这MsBuild配置,下面将简单的描述。

1:UsingTask:定义:<UsingTask TaskName="TaskName" AssemblyName = "AssemblyName" TaskFactory = "ClassName" Condition="'String A'=='String B'" />

描述我们的任务的程序集,任务类等信息,具体参见http://msdn.microsoft.com/zh-cn/library/t41tzex2.aspx

属性 说明

AssemblyName

AssemblyName 或 AssemblyFile 属性是必需的。

要加载的程序集的名称。尽管 AssemblyName 属性不是必需的,但它接受强名称程序集。使用此属性等效于通过 .NET Framework 中的 Load 方法加载程序集。

如果使用了 AssemblyFile 属性,便不能使用此属性。

AssemblyFile

AssemblyName 或 AssemblyFile 属性是必需的。

程序集的文件路径。此属性既接受完整路径,也接受相对路径。相对路径是相对于当前项目目录的路径。使用此属性等效于通过 .NET Framework 中的 LoadFrom 方法加载程序集。

如果使用了 AssemblyName 属性,便不能使用此属性。

TaskName

必选的属性。

要从程序集中引用的任务的名称。如果可能存在多义性,则此属性应该始终指定完整的命名空间。如果存在多义性,MSBuild 将选择任意匹配方式,该匹配方式可能产生意外的结果。

Condition

可选的属性。

要计算的条件。有关更多信息,请参见 MSBuild 条件

在系统中为我们定义了很多Task,有:

AL(程序集链接器)任务:描述  AL 任务及其参数。
AspNetCompiler 任务:包装 aspnet_compiler.exe,它是预编译 ASP.NET 应用程序的实用工具。
AssignCulture 任务:为项分配区域性标识符。
CallTarget 任务:调用项目文件中的目标。
Copy 任务:描述  Copy 任务及其参数。
CreateItem 任务:描述  CreateItem 任务及其参数。
CreateProperty 任务:描述  CreateProperty 任务及其参数。
Csc 任务:描述  Csc 任务及其参数。
Delete 任务:描述  Delete 任务及其参数。
Error 元素 (MSBuild):根据计算的条件语句停止生成操作并记录错误。
Exec 任务:描述  Exec 任务及其参数。
FindUnderPath 任务:确定指定项集合中的哪些项存在于指定的文件夹及其所有子文件夹中。
GenerateApplicationManifest 任务:描述  GenerateApplicationManifest 任务及其参数。
GenerateBootstrapper 任务:提供一种自动化方式来检测、下载和安装应用程序及其必备组件。
GenerateDeploymentManifest 任务:描述  GenerateDeployManifest 任务及其参数。
GenerateResource 任务:将 .txt 和 .resx 文件转换为公共语言运行库二进制 .resources 文件。
GetAssemblyIdentity 任务:从指定的文件检索程序集标识并输出标识信息。
GetFrameworkPath 任务:检索 .NET Framework 程序集的路径。
GetFrameworkSdkPath 任务:检索 .NET Framework SDK 的路径。
LC 任务:描述  LC 任务及其参数。
MakeDir 任务:描述  MakeDir 任务及其参数。
Message 元素 (MSBuild):在生成期间记录消息。
MSBuild 任务:描述 MSBuild 任务及其参数。
ReadLinesFromFile 任务:从文本文件读取项列表。
RegisterAssembly 任务:描述  RegisterAssembly 任务及其参数。
RemoveDir 任务:描述  RemoveDir 任务及其参数。
ResGen 任务:描述  ResGen 任务及其参数。
ResolveAssemblyReference 任务:描述  ResolveAssemblyReference 任务及其参数。
ResolveComReference 任务:描述  ResolveCOMReference 任务及其参数。
ResolveKeySource 任务:确定强名称密钥源
ResolveNativeReference 任务:解析本机引用。
SGen 任务:为指定程序集中的类型创建一个 XML 序列化程序集。
SignFile 任务:使用指定证书对指定文件进行签名。
Touch 任务:描述  Touch 任务及其参数。
UnregisterAssembly 任务:描述  UnregisterAssembly 任务及其参数。
Vbc 任务”描述  Vbc 任务及其参数。
VCBuild 任务“描述  VCBuild 任务及其参数。
Warning 元素 (MSBuild):根据计算的条件语句在生成期间记录警告。
WriteLinesToFile 任务:将指定项写入指定的文本文件。
其实很多我都不知道,我经常是用的时候在去查MSDN: http://msdn.microsoft.com/zh-cn/library/7z253716(v=VS.80).aspx

2:Target:定义

< Target  Name ="Target Name"  DependsOnTargets ="DependentTarget"  Inputs ="Inputs"  Outputs ="Outputs"  Condition ="'String A' == 'String B'" >   < Task > ...  </ Task >   < OnError...  />   </ Target >

描述了我们的目标:可以包含0个多个任务。

属性

 
属性 说明

Name

必选的属性。

目标的名称。

DependsOnTargets

可选的属性。

在执行此目标或者进行顶级依赖项分析之前必须执行的目标。多个目标之间用分号分隔。

Inputs

可选的属性。

此目标的项输入。此属性中的项用作顶级依赖项分析中的输入。

Outputs

可选的属性。

此目标的预期输出。可以通过对输入项应用转换来生成输出项。有关转换的更多信息,请参见 MSBuild 转换

Condition

可选的属性。

要计算的条件。如果条件的计算结果为 false,目标将不会执行该目标的体或者在 DependsOnTargets 属性中设置的任何目标的体。有关条件的更多信息,请参见 MSBuild

msdn:http://msdn.microsoft.com/zh-cn/library/t50z2hka(VS.80).aspx

参考文献:

http://msdn.microsoft.com/zh-cn/library/t41tzex2.aspx

http://msdn.microsoft.com/zh-cn/library/t50z2hka(VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/ms171466(v=VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/7z253716(v=VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/ms164313(v=VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/t9883dzc(v=VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/ms171464(v=VS.80).aspx

MSBuild概念:http://msdn.microsoft.com/zh-cn/library/ms171451(v=VS.80).aspx

 







 本文转自 破狼 51CTO博客,原文链接:http://blog.51cto.com/whitewolfblog/835134,如需转载请自行联系原作者

相关文章
|
6月前
|
IDE 开发工具 C++
插件:CLion中使用C/C++ Single File Execution插件编译和运行单个文件
插件:CLion中使用C/C++ Single File Execution插件编译和运行单个文件
600 0
|
7月前
|
IDE Java 开发工具
JDK 11中的源文件直接运行:从编译到执行的一步之遥
在JDK 11中,Java开发人员可以更轻松地将源代码直接转换为可执行程序,而无需经历传统的编译和打包过程。这一新功能简化了开发流程,提高了开发效率,为快速原型设计和即时应用程序部署提供了便利。本文将详细介绍JDK 11中源文件直接运行的技术细节、优势和适用场景。
|
7月前
|
C语言 C++
VScode中C++多文件编译运行问题(使用code runner配置)
VScode中C++多文件编译运行问题(使用code runner配置)
|
7月前
|
Ubuntu 网络安全 C语言
vscode 编译多个当前目录下cpp文件,报错未定义标识符的问题
vscode 编译多个当前目录下cpp文件,报错未定义标识符的问题
443 0
|
C++
Clion配置单个project下可以运行多个CPP文件的main函数
Clion配置单个project下可以运行多个CPP文件的main函数
1417 0
|
Ubuntu 编译器 Linux
[✔️]openal的编译指南
[✔️]openal的编译指南
490 0
|
存储 IDE Java
命令行下的Java包结构编译与执行
本文介绍命令行下的Java包结构编译与执行方法
155 0
命令行下的Java包结构编译与执行
|
自然语言处理
编译
编译
120 0
|
Web App开发 存储 缓存
V8 编译浅谈
本文是一个 V8 编译原理知识的介绍文章,旨在让大家感性的了解 JavaScript 在 V8 中的解析过程。
V8 编译浅谈
|
IDE 开发工具
刚刚编译运行的项目,突然就不能用了。AndroidStudio最难用
刚刚编译运行的项目,突然就不能用了。AndroidStudio最难用
97 0