当前位置: 首页 > news >正文

浅谈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,自定义任务需要去实现这个契约。其定义如下: 

   public   interface  ITask 
    { 
       IBuildEngine BuildEngine { 
get set ; } 
       ITaskHost HostObject { 
get set ; } 
       
bool  Execute(); 
    }

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

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

下面是一个简单的实现:

using  System; 
using  System.Collections.Generic; 
using  System.Linq; 
using  System.Text; 

namespace  FirstBuildTask 

    
public   class  MyBuildTask : Microsoft.Build.Utilities.Task 
    { 
        
private   string  outputFile; 

        [Microsoft.Build.Framework.Required] 
        
public   string  OutputFile 
        { 
            
get  {  return  outputFile; } 
            
set  { outputFile  =  value; } 
        } 

        
public   override   bool  Execute() 
        { 
            Log.LogWarning(
" test message: "   +   this .outputFile); 
            
return   true
        } 
    } 
}

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

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

程序

using  System; 
using  System.Collections.Generic; 
using  System.Linq; 
using  System.Text; 

namespace  BlogSample 

    
class  Program 
    { 
        
static   void  Main( string [] args) 
        { 
            Console.WriteLine(
" ok " ); 
            Console.Read(); 
        } 
    } 
}

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

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

声明Task:

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

添加任务:

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

修改后的csproject文件形如:

ExpandedBlockStart.gif View Code
<? xml version="1.0" encoding="utf-8" ?>  
< Project  ToolsVersion ="3.5"  DefaultTargets ="Build"  xmlns ="http://schemas.microsoft.com/developer/msbuild/2003%22> 
  <PropertyGroup> 
    <Configuration Condition="
 '$(Configuration)'  ==  '' " > Debug </ Configuration >  
    
< Platform  Condition =" '$(Platform)' == '' " > AnyCPU </ Platform >  
    
< ProductVersion > 9.0.30729 </ ProductVersion >  
    
< SchemaVersion > 2.0 </ SchemaVersion >  
    
< ProjectGuid > {844D0C87-9808-4AE9-8906-0382D9DDF88A} </ ProjectGuid >  
    
< OutputType > Exe </ OutputType >  
    
< AppDesignerFolder > Properties </ AppDesignerFolder >  
    
< RootNamespace > BlogSample </ RootNamespace >  
    
< AssemblyName > BlogSample </ AssemblyName >  
    
< TargetFrameworkVersion > v3.5 </ TargetFrameworkVersion >  
    
< FileAlignment > 512 </ FileAlignment >  
  
</ PropertyGroup >  
  
< PropertyGroup  Condition =" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " >  
    
< DebugSymbols > true </ DebugSymbols >  
    
< DebugType > full </ DebugType >  
    
< Optimize > false </ Optimize >  
    
< OutputPath > bin\Debug\ </ OutputPath >  
    
< DefineConstants > DEBUG;TRACE </ DefineConstants >  
    
< ErrorReport > prompt </ ErrorReport >  
    
< WarningLevel > 4 </ WarningLevel >  
  
</ PropertyGroup >  
  
< PropertyGroup  Condition =" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " >  
    
< DebugType > pdbonly </ DebugType >  
    
< Optimize > true </ Optimize >  
    
< OutputPath > bin\Release\ </ OutputPath >  
    
< DefineConstants > TRACE </ DefineConstants >  
    
< ErrorReport > prompt </ ErrorReport >  
    
< WarningLevel > 4 </ WarningLevel >  
  
</ PropertyGroup >  
  
< ItemGroup >  
    
< Reference  Include ="System"   />  
    
< Reference  Include ="System.Core" >  
      
< RequiredTargetFramework > 3.5 </ RequiredTargetFramework >  
    
</ Reference >  
    
< Reference  Include ="System.Xml.Linq" >  
      
< RequiredTargetFramework > 3.5 </ RequiredTargetFramework >  
    
</ Reference >  
    
< Reference  Include ="System.Data.DataSetExtensions" >  
      
< RequiredTargetFramework > 3.5 </ RequiredTargetFramework >  
    
</ Reference >  
    
< Reference  Include ="System.Data"   />  
    
< Reference  Include ="System.Xml"   />  
  
</ ItemGroup >  
  
< ItemGroup >  
    
< Compile  Include ="DisposeSubstance.cs"   />  
    
< Compile  Include ="Program.cs"   />  
    
< Compile  Include ="Properties\AssemblyInfo.cs"   />  
  
</ ItemGroup >  
  
< Import  Project ="$(MSBuildToolsPath)\Microsoft.CSharp.targets"   />  
< UsingTask  TaskName ="MyBuildTask"  AssemblyFile ="XXXXX\bin\Debug\FirstBuildTask1.dll" />  
  
< Target  Name ="BeforeBuild" >  
  
</ Target >  
  
< Target  Name ="AfterBuild" >  
< MyBuildTask  OutputFile ="$(MSBuildProjectFullPath)" />  
  
</ Target >  
</ Project >

此时我们可以用VS重新加载编译或者是MSBuild控制台编译:

效果如下:

image

上边红线注释的就是我们的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

AssemblyNameAssemblyFile 属性是必需的。

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

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

AssemblyFile

AssemblyNameAssemblyFile 属性是必需的。

程序集的文件路径。此属性既接受完整路径,也接受相对路径。相对路径是相对于当前项目目录的路径。使用此属性等效于通过 .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

相关文章:

  • AjaxPro.Net的使用
  • 推荐20个优秀的网页色彩搭配实例
  • 系统集成资质培训 - 2011年下半年培训机构
  • [毕业生的商业软件开发之路]C#可访问级别
  • OUTLOOK EXPRESS邮件以及邮件夹都没有了,请教!急!!!
  • 分享一些经典资源
  • 北电ERS1600,8300,8600交换机的基本技术-汇总6-10
  • struts2的验证框架
  • rsyslog + mysql
  • Google已经获得www.baidu.com.sb域名
  • P2P下载为什么人越多越快呢??
  • php修改删除xml内容
  • An Introduction to Shiro (formerly JSecurity) – A Beginner’s Tutorial Part 1
  • 去网络视频广告方法——虽过时,但效果依然很好(亲测)
  • 评国内三大B2C网站首页的信息架构
  • [LeetCode] Wiggle Sort
  • 30天自制操作系统-2
  • C++11: atomic 头文件
  • Github访问慢解决办法
  • iOS 系统授权开发
  • JavaScript的使用你知道几种?(上)
  • Koa2 之文件上传下载
  • Laravel 实践之路: 数据库迁移与数据填充
  • Mithril.js 入门介绍
  • nginx 配置多 域名 + 多 https
  • node.js
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • SpiderData 2019年2月16日 DApp数据排行榜
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 动态魔术使用DBMS_SQL
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 规范化安全开发 KOA 手脚架
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 聊聊flink的TableFactory
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 小试R空间处理新库sf
  • 学习笔记:对象,原型和继承(1)
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 用Canvas画一棵二叉树
  • AI算硅基生命吗,为什么?
  • const的用法,特别是用在函数前面与后面的区别
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​比特币大跌的 2 个原因
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #pragma once
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测