一、前言
MSBuild是一個既熟悉又陌生的名字,Visual Studio的項目加載和構建均通過MSBuild來實現。VS中右鍵打開項目菜單,對應MSBuild的Build目標,
對應MSBuild的Rebuild目標,
對應MSBuild的Clean目標,
對應MSBuild的PublishOnly目標。到這里我想大家都明白MSBuild就和Ant一樣就是一個用于項目構建的任務執行引擎,只不過它被融入到VS中,降低了入門難度。但融入VS中只是方便我們使用而已,并不代表不用了解學習,尤其項目規模愈發龐大時,編寫結構良好的MSBuild Script來作為項目構建和管理的基石是必不可少。
本文是近日的學習記錄,學習目標是看懂*.csproj項目文件的信息。若有紕漏請大家指正,謝謝。
附件知識 :
*.sln : 項目、解決方案在磁盤上的引用,VS通過該類文件加載整個項目、解決方案;
*.suo : 保存VS用戶界面的自定義配置(包括布局、斷電和項目最后編譯后而又沒有關閉的文件標簽等),下一次打開VS時會恢復這些配置;
*.csproj.user: 保存VS的個人配置;
*.csproj : XML格式,保存項目的依賴項和項目構建步驟、任務等。(需要上傳到版本庫的)
注意:以下內容均以.NET Framework 4.0為環境。
目錄一大坨:
MSBuild由兩部分組成:腳本 和 執行引擎。
腳本:就是帶變量、函數、流程控制的可編程語言。MSBuild Script是基于XML schema的,和Ant、Maven等差不多。
執行引擎:以腳本、變量、環境變量作為輸入,對腳本進行解析執行。
直接到MSDN學習是一個不錯的選擇,但為了降低學習難度我們以**.csproj項目文件作為切入點。
在VS2013下新建名為LearnMSBuild的MVC4項目,然后在項目目錄下有LearnMSBuild.csproj和LearnMSBuild.csproj.user兩個項目文件,而里面就是MSBuild Script了。
在VS中查看LearnMSBuild.csproj的方法:右鍵點擊項目->卸載項目->右鍵點擊項目->編輯LearnMSBuild.csproj。

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion> </ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{13508D65-AC7D-4462-9106-2E8EC81F677D}</ProjectGuid> <ProjectTypeGuids>{E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>MvcApplication1</RootNamespace> <AssemblyName>MvcApplication1</AssemblyName> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <MvcBuildViews>false</MvcBuildViews> <UseIISExpress>true</UseIISExpress> <IISExpressSSLPort /> <IISExpressAnonymousAuthentication /> <IISExpressWindowsAuthentication /> <IISExpressUseClassicPipelineMode /> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\</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\</OutputPath> <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> <Reference Include="Microsoft.CSharp" /> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Data.Entity" /> <Reference Include="System.Drawing" /> <Reference Include="System.Web.DynamicData" /> <Reference Include="System.Web.Entity" /> <Reference Include="System.Web.ApplicationServices" /> <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Core" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Web" /> <Reference Include="System.Web.Extensions" /> <Reference Include="System.Web.Abstractions" /> <Reference Include="System.Web.Routing" /> <Reference Include="System.Xml" /> <Reference Include="System.Configuration" /> <Reference Include="System.Web.Services" /> <Reference Include="System.EnterpriseServices" /> <Reference Include="EntityFramework"> <HintPath>..\packages\EntityFramework.5.0.0\lib\net40\EntityFramework.dll</HintPath> </Reference> <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> </Reference> <Reference Include="Microsoft.Web.Mvc.FixedDisplayModes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll</HintPath> </Reference> <Reference Include="Newtonsoft.Json"> <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="System.Net.Http"> <Private>True</Private> <HintPath>..\packages\Microsoft.Net.Http.2.0.30506.0\lib\net40\System.Net.Http.dll</HintPath> </Reference> <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath> </Reference> <Reference Include="System.Net.Http.WebRequest"> <Private>True</Private> <HintPath>..\packages\Microsoft.Net.Http.2.0.30506.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath> </Reference> <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath> </Reference> <Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.30506.0\lib\net40\System.Web.Http.WebHost.dll</HintPath> </Reference> <Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath> </Reference> <Reference Include="System.Web.Optimization"> <HintPath>..\packages\Microsoft.AspNet.Web.Optimization.1.0.0\lib\net40\System.Web.Optimization.dll</HintPath> </Reference> <Reference Include="System.Web.Providers"> <HintPath>..\packages\Microsoft.AspNet.Providers.Core.1.2\lib\net40\System.Web.Providers.dll</HintPath> </Reference> <Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll</HintPath> </Reference> <Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.dll</HintPath> </Reference> <Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath> </Reference> <Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath> </Reference> <Reference Include="WebGrease"> <Private>True</Private> <HintPath>..\packages\WebGrease.1.3.0\lib\WebGrease.dll</HintPath> </Reference> <Reference Include="Antlr3.Runtime"> <Private>True</Private> <HintPath>..\packages\WebGrease.1.3.0\lib\Antlr3.Runtime.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> <Compile Include="App_Start\BundleConfig.cs" /> <Compile Include="App_Start\FilterConfig.cs" /> <Compile Include="App_Start\RouteConfig.cs" /> <Compile Include="App_Start\WebApiConfig.cs" /> <Compile Include="Global.asax.cs"> <DependentUpon>Global.asax</DependentUpon> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> <Content Include="Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png" /> <Content Include="Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png" /> <Content Include="Content\themes\base\images\ui-icons_222222_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_2e83ff_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_454545_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_888888_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_cd0a0a_256x240.png" /> <Content Include="Content\themes\base\jquery-ui.css" /> <Content Include="Content\themes\base\jquery.ui.accordion.css" /> <Content Include="Content\themes\base\jquery.ui.all.css" /> <Content Include="Content\themes\base\jquery.ui.autocomplete.css" /> <Content Include="Content\themes\base\jquery.ui.base.css" /> <Content Include="Content\themes\base\jquery.ui.button.css" /> <Content Include="Content\themes\base\jquery.ui.core.css" /> <Content Include="Content\themes\base\jquery.ui.datepicker.css" /> <Content Include="Content\themes\base\jquery.ui.dialog.css" /> <Content Include="Content\themes\base\jquery.ui.progressbar.css" /> <Content Include="Content\themes\base\jquery.ui.resizable.css" /> <Content Include="Content\themes\base\jquery.ui.selectable.css" /> <Content Include="Content\themes\base\jquery.ui.slider.css" /> <Content Include="Content\themes\base\jquery.ui.tabs.css" /> <Content Include="Content\themes\base\jquery.ui.theme.css" /> <Content Include="Content\themes\base\minified\images\ui-bg_flat_0_aaaaaa_40x100.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_flat_75_ffffff_40x100.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_55_fbf9ee_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_65_ffffff_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_75_dadada_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_75_e6e6e6_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_95_fef1ec_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_highlight-soft_75_cccccc_1x100.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_222222_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_2e83ff_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_454545_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_888888_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_cd0a0a_256x240.png" /> <Content Include="Content\themes\base\minified\jquery-ui.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.accordion.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.autocomplete.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.button.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.core.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.datepicker.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.dialog.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.progressbar.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.resizable.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.selectable.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.slider.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.tabs.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.theme.min.css" /> <Content Include="Global.asax" /> <Content Include="Content\Site.css" /> <None Include="Scripts\jquery-1.8.2.intellisense.js" /> <Content Include="Scripts\jquery-1.8.2.js" /> <Content Include="Scripts\jquery-1.8.2.min.js" /> <None Include="Scripts\jquery.validate-vsdoc.js" /> <Content Include="Scripts\jquery-ui-1.8.24.js" /> <Content Include="Scripts\jquery-ui-1.8.24.min.js" /> <Content Include="Scripts\jquery.unobtrusive-ajax.js" /> <Content Include="Scripts\jquery.unobtrusive-ajax.min.js" /> <Content Include="Scripts\jquery.validate.js" /> <Content Include="Scripts\jquery.validate.min.js" /> <Content Include="Scripts\jquery.validate.unobtrusive.js" /> <Content Include="Scripts\jquery.validate.unobtrusive.min.js" /> <Content Include="Scripts\knockout-2.2.0.debug.js" /> <Content Include="Scripts\knockout-2.2.0.js" /> <Content Include="Scripts\modernizr-2.6.2.js" /> <Content Include="Scripts\_references.js" /> <Content Include="Web.config" /> <Content Include="Web.Debug.config"> <DependentUpon>Web.config</DependentUpon> </Content> <Content Include="Web.Release.config"> <DependentUpon>Web.config</DependentUpon> </Content> <Content Include="Views\Web.config" /> <Content Include="Views\_ViewStart.cshtml" /> <Content Include="Views\Shared\Error.cshtml" /> <Content Include="Views\Shared\_Layout.cshtml" /> </ItemGroup> <ItemGroup> <Folder Include="App_Data\" /> <Folder Include="Controllers\" /> <Folder Include="Models\" /> </ItemGroup> <ItemGroup> <Content Include="packages.config" /> </ItemGroup> <PropertyGroup> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> </PropertyGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" /> <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'"> <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" /> </Target> <ProjectExtensions> <VisualStudio> <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> <WebProjectProperties> <UseIIS>True</UseIIS> <AutoAssignPort>True</AutoAssignPort> <DevelopmentServerPort>40646</DevelopmentServerPort> <DevelopmentServerVPath>/</DevelopmentServerVPath> <IISUrl>http://localhost:40646/</IISUrl> <NTLMAuthentication>False</NTLMAuthentication> <UseCustomServer>False</UseCustomServer> <CustomServerUrl> </CustomServerUrl> <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> </WebProjectProperties> </FlavorProperties> </VisualStudio> </ProjectExtensions> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> --> <ItemGroup> <F Include="test.txt"> <OP>tst/</OP> </F> <F Include="test1.txt"> <OP>tst/</OP> </F> </ItemGroup> <Target Name="HW" Inputs="@(F)" Outputs="@(F->'%(OP)%(Filename)%(Extension)')"> <Message Text="%(F.OP)"/> <Copy SourceFiles="@(F)" DestinationFolder="%(F.OP)" /> </Target> </Project>
作用:根節點,用于配置項目級信息。
屬性名 | 說明 |
ToolsVersion | 指定執行引擎的版本號 |
InitialTargets | 指定初始化時執行的目標組,多個目標間通過分號(;)分隔 |
DefaultTargets | 指定默認執行的目標組,多個目標間通過分號(;)分隔 |
ItemGroup 用于對N個Item元素進行分類整理,并可通過Condition屬性對旗下的Item元素進行是否生效的統一控制。
Item
作用:對一個或多個文件的命名引用。可包含元數據(如文件名、路徑和版本號),元數據均以子元素的形式定義。
屬性名 | 說明 |
Include | 指定引入的文件絕對/相對路徑 或 程序集名,多個值間通過分號(;)分隔 |
Exclude | 指定不引入的文件絕對/相對路徑 或 程序集名,多個值間通過分號(;)分隔 |
Condition | 判斷是否生效 |
獲取Item的Include值: @(ItemType, Separator) ,Separator默認是分號(;) |
Item的子元素作為其元數據。獲取元數據: %(ItemType.ItemMetadata)
示例——定義名為Script的Item
<Script Include="Script/jquery.js;Script/app.js"> <Version>0.1</Version> </Script> <Target Name="Nothing"> <Message Text="@(Script)+%(Script.Version)" /> </Target> // 執行結果:Script/jquery.js;Script/app.js+01
MSBuild執行引擎中內置部分預定義的Item,具體如下:
Item名 | 元數據名 | 元數據說明 |
Reference (設置程序集(托管)引用) | HintPath | 程序集的絕對或相對路徑 |
Name | 程序集的顯示名稱 | |
FusionName | 程序集的強簽名名稱 | |
SpecificVersion | true表示程序集版本號必須與FunsionName指定的一致;false表示不必一致 | |
Aliases | 程序集的別名 | |
Private | 用于決定是否將程序集賦值到輸出目錄中。Never/Always(默認值)/PreserveNewest | |
Compile (編譯器的源文件) | DependentUpon | 指出文件正確編譯所依賴的文件 |
AutoGen | true表示由VS為項目生成的文件 | |
Link | 文件在物理上處于項目文件的影響范圍之外時要顯示的符號路徑 | |
Visible | true表示在 Visual Studio 中的“解決方案資源管理器”中顯示文件 | |
CopyToOutputDirectory | 確定是否將文件復制到輸出目錄。Never/Always(默認值)/PreserveNewest | |
Content (表示不會編譯到項目中,但可能會嵌入其中或隨其一起發布的文件) | DependentUpon | 依賴文件 |
Generator | 文件生成器的名稱 | |
LastGenOutput | 文件生成器創建的文件的名稱 | |
CustomToolNamespace | 文件生成器應在其中創建代碼的命名空間 | |
Link | true表示在VS中的解決方案資源管理器中顯示文件 | |
PublishState | 內容的發布狀態.Default/Included/Excluded/DataFile/必備組件 | |
IsAssembly | true表示是文件時程序集 | |
Visible | true表示在VS中的解決方案資源管理器中顯示文件 | |
CopyToOutputDirectory | 確定是否將文件復制到輸出目錄。Never/Always(默認值)/Pre | |
None(表示不應在生成過程中具有角色的文件,但同樣可輸出到生成目錄中(默認是不輸出到生成目錄和不發布)) | DependentUpon | 依賴文件 |
Generator | 文件生成器的名稱 | |
LastGenOutput | 文件生成器創建的文件的名稱 | |
CustomToolNamespace | 文件生成器應在其中創建代碼的命名空間 | |
Link | 文件在物理上處于項目的影響范圍之外時要顯示的符號路徑 | |
Visible | true表示在VS中的解決方案資源管理器中顯示文件 | |
CopyToOutputDirectory | 確定是否將文件復制到輸出目錄。Never/Always(默認值)/PreserveNewest | |
COMReference (COM(非托管)組件引用) | ||
COMFileReference (饋送到ResolvedComreference目標中的類型庫的列表) |
||
NativeReference (本機清單文件或對此類文件的引用) | ||
ProjectReference (對另一個.proj文件的引用) | ||
BaseApplicationManifest (表示用于生成的基本應用程序清單,包含ClickOnce部署安全信息) | ||
CodeAnalysisImport (表示要導入的FxCop項目) | ||
EmbeddedResource(要在生成的程序集中嵌入的資源) | ||
Import (表示應由Visual Basic編譯器導入其命名空間的程序集) |
MSBuild執行引擎中為每個Item預設的元數據,具體如下:
元數據名 | 元數據說明 |
FullPath | 當前項所指向的文件的絕對路徑 |
RootDir | 當前項所指向的文件的根目錄 |
Filename | 當前項所指向的文件的不含擴展名的名稱 |
Extension | 當前項所指向的文件的擴展名 |
RelativeDir | 當前項所指向的文件的相對路徑(以\為結尾) |
Directory | 當前項所指向的文件的目錄(以\為結尾) |
RecursiveDir | 當項的Include中包含**,則存放**匹配到的目錄路徑 |
Identity | %(RelativeDir)\%(Filename)%(Extension) |
ModifiedTime | 最后修改時間 |
CreatedTime | 創建時間 |
AccessedTime | 最后訪問時間 |
示例:
<MyItem Include="HelloWorld.cs"> </MyItem> <Target Name="Test"> <Message Text="%(MyItem.FileName)"/> </Target // 輸出 HelloWorld
*元數據轉換(MSBuild Transform)*
增量生成就會用到MSBuild Transform。
作用:將一組Item轉換為一組輸出值
語法: @(ItemType->'%(metadata)')
<Target Name="CopyOutputs" Inputs="@(BuiltAssemblies)" Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')"> <Copy SourceFiles="@(BuiltAssemblies)" DestinationFolder="$(OutputPath)"/> </Target> 假定BuiltAssemblies如下 <BuiltAssemblies Include="a.txt"></BuiltAssemblies> <BuiltAssemblies Include="b.txt"></BuiltAssemblies> <BuiltAssemblies Include="c.txt"></BuiltAssemblies> Inputs="@(BuiltAssemblies)" Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')" 會建立以下的mapping a.txt(時間戳) <-> bin\a.txt(時間戳) b.txt(時間戳) <-> bin\b.txt(時間戳) c.txt(時間戳) <-> bin\c.txt(時間戳) 在執行Target時,會根據Mapping來檢查兩者的時間戳,若Output的沒有時間戳或小于Input的時間戳則該Input項會列入執行的范圍,否則則不再被解析執行。
PropertyGroup:屬性組,用于整理歸類Property
Property:配置信息的鍵值對
項 | 明細 |
示例 |
定義屬性 | <屬性名>屬性值</屬性名> | <buildMode>debug</buildMode> |
調用 | $(屬性名) | <Message Text="$(buildMode)"></Message> |
注意 | 在啟動執行引擎時,可從通過/property選項設置,并在腳本中通過$(屬性名)的方式來引用 | shell> MSBuild /property:buildMode=release 腳本文件路徑 |
在啟動執行引擎時,可從腳本中通過$(屬性名)的方式來引用 | ||
在啟動執行引擎時,MSBuild預留一些保留屬性,供腳本引用 | $(MSBuildProjectDirectory) 項目所在的目錄 | |
$(MSBuildProjectFileName) 項目文件的含擴展名的文件名 | ||
$(MSBuildProjectExtension) 項目文件的擴展名 | ||
$(MSBuildProjectFullPath) 項目文件的完整路徑 | ||
$(MSBuildProjectName) 不帶擴展名的項目文件的文件名 | ||
$(MSBuildBinPath) MSBuild所在的目錄 |
執行具體任務的任務執行程序。
屬性:
屬性名 | 說明 | ||
Condition | 生效條件 | ||
ContinueOnError |
.NET Framework4.5前只支持true和false |
WarnAndContinue | 當任務失敗時,報警告,當會繼續執行 |
true | 當任務失敗時,報警告,當會繼續執行 | ||
ErrorAndContinue | 當任務失敗時,報錯誤,當會繼續執行 | ||
ErrorAndStop | 當任務失敗時,包錯誤,且不會繼續執行 | ||
false | 當任務失敗時,包錯誤,且不會繼續執行 | ||
Parameter | 實參,如 Name="fsjohnhuang" |
子元素:
子元素 | 屬性名 | 說明 |
Output | TaskParameter | 輸出參數的名稱 |
PropertyName | 接收任務輸出參數值的屬性,后續可通過$(PropertyName)來引用該屬性。PropertyName和ItemName存在互斥關系 | |
ItemName | 接收任務輸出參數值的項,后續可通過@(ItemName)來引用該項。PropertyName和ItemName存在互斥關系 | |
Condition | 生效條件 |
<Target Name="Compile" DependsOnTargets="Resources"> <Csc Sources="@(CSFile)" TargetType="library" Resources="@(CompiledResources)" EmitDebugInformation="$(includeDebugInformation)" References="@(Reference)" DebugType="$(debuggingType)" OutputAssembly="$(builtdir)\$(MSBuildProjectName).dll" > <Output TaskParameter="OutputAssembly" ItemName="FinalAssemblyName" /> <Output TaskParameter="BuildSucceeded" PropertyName="BuildWorked" /> </Csc> </Target>
分類:
分類 | 說明 |
示例 |
MSBuild內置任務執行程序 | 由MSBuild預定義的任務執行程序,如Csc、Message等 | <Message Text="HelloWrold!"/> |
外部任務執行程序 | 通過MSBuild內置任務執行程序Exec來調用操作系統內的任意程序來執行任務 |
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Binaries Include="*.dll;*.exe"/> </ItemGroup> <Target Name="SetACL"> <!-- set security on binaries--> <Exec Command="echo y| cacls %(Binaries.Identity) /G everyone:R"/> </Target> </Project> |
自定義任務執行程序 |
繼承ITask接口 1. 若要覆蓋MSBuild內置任務執行程序則將程序集保存在.NET Framework的目錄下,并且后綴必須為.OverrideTasks或.Tasks; 2. 若不覆蓋,則通過UsingTask元素的AssemblyFile或AssemblyName屬性引入。 |
|
通過UsingTask來定義內聯任務(.NET Framework 4 的特性) |
作用:定義和引入任務執行程序
屬性:
屬性名 | 說明 |
注意 |
AssemblyName | 要加載的程序集的名稱,設置后不能設置AssemblyFile | 任務的實現類,必須繼承ITask接口 |
AssemblyFile | 要加載的程序集的路徑,設置后不能設置AssemblyName | 任務的實現類,必須繼承ITask接口 |
TaskFactory | 指定用于創建Task實例的工廠類 | |
TaskName | 任務名稱 | |
Condition | 生效條件 |
子元素:
元素 | 元素屬性/子元素 | 屬性/子元素說明 | 元素屬性/子元素 | 屬性/子元素說明 | 示例 |
ParameterGroup 包含參數列表 | Parameter元素 | 參數 | ParameterType | 參數類型 |
<ParameterGroup> |
Required | true:必要參數 | ||||
Output | 和C#的out一樣 | ||||
TaskBody | Evaludate | true: 表示TaskBody子元素將被計算并運用到TaskFactory中 | |||
Task (用于定義內聯任務) |
定義內聯任務——Task元素詳解
1. 直接在項目文件中編寫任務,而不必引用外部包含繼承ITask接口的類的程序集
2. 可用支持.NET CodeDom 語言(例如,Visual Basic、Visual C# 或 JScript)來編寫任務邏輯
子元素:
元素 | 屬性/子元素 | 屬性/子元素說明 |
Reference (如同在VS中通過引入程序集一樣) | ||
Using (如同C# 的Using) | ||
Code (編寫代碼) | Type |
代碼類型,值如下: Class (Code元素包含派生自ITask接口的類代碼) Method (Code元素包含定義ITask接口的Execute方法的重寫(方法簽名+方法體)) Fragment (Code元素中僅包含Execute方法的方法體代碼) |
Language |
編碼的語言,值如下: cs (C#) VB(vbs) |
|
Source |
指定存儲Code子元素的文件路徑 1. 設置Source后,Type默認為Class 2. 不設置Source,Type默認為Fragment |
|
子元素<![CDATA[代碼]]> |
任務實現的代碼 |
注意:當UsingTask中出現子元素Task時,則UsingTask的屬性TaskFactory必須為CodeTaskFactory,AssemblyFile為$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll。
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <UsingTask TaskName="Nothing" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll"> <ParameterGroup/> <Task Type="Fragment" Language="cs"> <Reference Include="System.Core"/> <Using Namespace="System" /> <Using Namespace="System.IO" /> <Using Namespace="System.Net" /> <Using Namespace="Microsoft.Build.Framework" /> <Using Namespace="Microsoft.Build.Utilities" /> <Code Type="Fragment" Language="cs"> <![CDATA[ try { OutputFilename = Path.GetFullPath(OutputFilename); Log.LogMessage("Downloading latest version of NuGet.exe..."); WebClient webClient = new WebClient(); webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename); return true; } catch (Exception ex) { Log.LogErrorFromException(ex); return false; } ]]> </Code> </Task> </Project>
作用:針對某項工作,有序地組織多個Task。是對外的最小執行單位
屬性:
屬性名 | 說明 |
Name | 目標名稱 |
DependsOnTargets | 在執行該目標前,先執行指定的目標。多個目標時,通過分號(;)分隔 |
Condition | 生效條件 |
Inputs | 指定存儲目標輸入的文件路徑,多個文件路徑間通過分號(;)分隔 |
Outputs | 指定存儲目標輸出的文件路徑,多個文件路徑間通過分號(;)分隔 |
BeforeTargets | 執行指定的目標(多個目標間通過分號分隔)前,先要執行當前目標 |
AfterTargets | 執行指定的目標(多個目標間通過分號分隔)后,要執行當前目標 |
Label | 標識 |
KeepDuplicateOutputs | true:Outputs中含有多個重復的Reference不會被排重。默認為false |
Returns | 目標的一組返回項,返回給調用該目標的任務。若沒有設置該項,則會返回Outputs的內容 |
子元素:
元素 | 屬性 | 屬性說明 |
OnError (存在多個OnError元素時,目標失敗后會按順序依次執行) | ExecuteTargets | 指定任務失敗時執行的目標(多個目標間通過分號分隔) |
Condition | 生效條件 |
注意:1.一次生成過程僅會執行同一個Target一次,當出現重復調用時會忽略,且返回第一次調用后的返回值;
2.Target重復定義時,采取最后定義有效的原則
作用:根據條件使部分Property/PropertyGroup/ItemGroup生效
子元素:
元素 | 說明 |
When | <When Condition="'StringA' == 'StringB'">成立即生效</When> |
Otherwise | <Otherwise>所有When均不成立即生效</Otherwise> |
作用:將另一個項目文件導入到當前的項目文件
屬性:
屬性名 | 說明 |
Project 項目文件的絕對或相對路徑 |
1. 相對路徑,是相對于當前項目文件的路徑而言; 2. 可使用通配符(*,**和?) |
Condition | 生效條件 |
注意:1. 若當前項目文件沒有DefaultTargets屬性,則會按引入順序尋找各被導入的項目文件的DefaultTargets屬性,并執行第一個搜索到的DefaultTargets屬性值;
2. 共享的導入項目文件的命名規范是以.targets作為擴展名(如:.nuget/NuGet.targets)
ImportGroup元素用于組織整理Import元素。
作用:內部包含的內容,將不被MSBuild解析執行
特殊字符:在MSBuild Script有特殊含義和用途的字符,若將它們作為普通字符輸出時,需要通過%xx,xx為字符的ASCII的十六進制值的字面量來表示。
特殊字符 | %xx字面量 |
* | %2A |
% | %25 |
@ | %40 |
' | %27 |
? | %3F |
$ | %24 |
; | %3B |
斷言/作用 | 語法 |
等于 | 'stringA' == 'stringB' |
不等于 | 'stringA' != 'stringB' |
小于、大于、小于等于和大于等于 | <,>,<=,>= |
存在 | Exists('stringA') |
以正斜線為結尾 | HasTrailingSlash('stringA') |
非 | ! |
邏輯與 | And |
邏輯或 | Or |
提高優先級 | () |
假定目錄結構為
workspace
|-------- i.gif
| test.gif
|-------- cd
|------- c.gif
通配符 | 說明 | 示例 |
* | 配置任意數量的任意字符,僅限于文件級別 |
1. *.gif匹配出 i.gif和test.gif 2. t*.gif匹配出 test.gif |
** | 配置無限制的目錄級別 |
1. **匹配出 i.gif、test.gif和cd/c.gif 2. **/*.gif匹配出 cd/c.gif |
? | 配置一個任意字符 |
?.gif匹配出 i.gif |
MSBuild.exe <SolutionName>.sln /t:<ProjectName>:<TargetName>[;<ProjectName>:<TargetName>]*
本文主要是針對**.csproj中出現的元素來學習MSBuild Script,日后理論*實踐后繼續補充。
尊重原創,轉載請注明來自:^_^肥子John http://www.cnblogs.com/fsjohnhuang/p/4490562.html
https://msdn.microsoft.com/zh-cn/library/dd637714.aspx
文章列表