使用MSBuild实现完整daily build流程 .
来源:互联网 发布:php 创建log文件 编辑:程序博客网 时间:2024/06/09 04:13
一、MSBuild
在微软软件开发中,每日构建是最重要的过程之一,被称为微软产品开发的“心跳”。简单来看,每天构建系统将整个产品解决方案完整构建一遍,生成的目标文件和安装文件被放置在一个共享位置。接着,安装文件被自动部署到release server上,随后可以自动运行BVT(build verification test),并将所有结果寄送每个team member的信箱。
微软有一套完善的内部系统来完成整个自动化流程,以及流程管理、reporting等工作,而如果我们没有这套系统,也想实现完整的daily build流程,该怎么做呢?
在VS.NET2003时代,IDE可以控制整个方案的构建,但是所有的构建逻辑被IDE控制,对于开发人员来说,整个构建流程就像一个黑箱,很难修改和管理。当然可以使用PreBuildEvent和PostBuildEvent来控制,但是这些event都写在csproj/vbproj文件中,不便于修改,不适于扩展。而且使用IDE来做每日构建的话,要求构建系统本身装有VS.NET,这会带来额外的成本。另一种办法是使用NAnt,通过XML配置文件,来管理构建流程,这会使得整个流程易于修改,可扩展,并且不要求构建系统安装IDE,只需要有framework即可。问题是使用NAnt必须额外写一堆复杂的XML配置文件,足以让很多developer看了头疼。
VS.NET2005中引入了一套全新的构建系统:MSBuild。简单来讲,MSBuild可以直接读取csproj文件,控制csc/vbc等编译器,生成整个方案。实际上,VS2005的IDE自身就是调用MSBuild来完成编译的,这与VS2003有很大的不同。并且由于VS2005的csproj文件服从MSBuild的配置schema,因此我们可以直接使用csproj,稍稍修改一下,就能组织起完整的构建流程了。
二、示例项目的组织
来看一个完整的例子。
我们将建立一个简单的Hello方案,包括一个HelloService(Windows NT Service),一个HelloSite(ASP.NET Web Site),和一个共用组件(class library)。如图所示。
build目录中,将用来存放构建使用的配置文件。private目录中存放解决方案本身。public目录中存放用来完成构建所使用的编译器,例如WiX(用来生成安装包)。先在private目录中新建一个空解决方案,可以命名为“HelloSolution”。然后依次新建SharedComponents、HelloService和HelloSite项目,并建立引用关系:HelloService引用了SharedComponents。最后的文件组织如图所示。
注释:没有贴图,到CSDN下载,有人提供了,这个文章是在其他地方转载的。
删除Default.aspx第一行的引用,删除Default.aspx.cs,添加一个App_Code目录,在App_Code中新建一个Hello.cs文件,保持初始代码不用修改。
在IDE中编译整个Solution,没问题。可以关闭IDE了。
打开SDK的控制台,输入两条命令:
CD /d C:\Hello\private\HelloSolution
msbuild
//没有找到MSBUILD.EXE的方法:
//建立一个批处理BuildAndDeploy.bat
@echo off
set Configuration=Debug
set BuildTargets=ReBuild
set Deploy=1
@echo on
%SystemRoot%\Microsoft.NET\Framework\v3.5\MSBuild.exe
..\..\_ci\projects\build.proj
/fl1 /flp1:LogFile=Build.log;Verbosity=Normal
pause
很快就能看到构建结果了:
编译csproj不仅仅限于.sln,或者msbuild.proj,
proj是一个XML的自动化构建工具,不同的版本需要选定不同的.NET Framework.
很快就能看到构建结果了:
但这并不完全是我想要的。例如我想将所有的项目输出都放在C:\Hello\target目录;我想让HelloSite有一个自己的主目录;我想自动生成MSI安装包,并且也放在target目录下。
三、修改构建流程
首先我们将SharedComponent.csproj和HelloService.csproj文件copy至build目录下,并将扩展名改名为proj。用记事本打开SharedComponents.proj,看到如下内容。
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{FF79BA82-D6CE-4E89-9AFA-C5EF83A62C2D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SharedComponents</RootNamespace>
<AssemblyName>SharedComponents</AssemblyName>
</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.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- 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>
-->
</Project>
观察可以发现,红色的部分是给VS IDE用的,与MSBuild无关,因此可以删除。最后几行中的BeforeBuild和AfterBuild暂时没用,也可以删除。
从第一行开始看:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
首先看到一个属性组,里面的每一条属性都可以理解成一个环境变量。属性组第一行是说,如果环境变量“Configuration”为空,那么设置属性 “Configuration”为“Debug”。同样,第二行是说,如果环境变量“Platform”为空,那么设置属性“Platform”为“AnyCPU”。这里我不想使用“AnyCPU”,于是将其改成“x86”。
<OutputType>Library</OutputType>
<AssemblyName>SharedComponents</AssemblyName>
</PropertyGroup>
OutputType指定了输出类型为类库。AssemblyName指定输出文件名,改为Hello.SharedComponents。
<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>
在这一段中,如果Configuration属性并上“|” 并上Platform属性,等于“Debug|AnyCPU”的话,那么定义一个属性组。换句话说,就是为debug、AnyCPU的组合配置一段编译器使用的属性。将第一行的Condition改成“'$(Configuration)' == 'Debug'”(假设我们并不需要在其它platform上进行编译)。以同样的方式修改Release的PropertyGroup。
接着是一个ItemGroup,指定了这个项目引用的组件。
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
然后又是一个ItemGroup,指定了参加编译的源代码文件。
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
再接下来,引入了一个targets文件:
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
$(MSBuildBinPath)是一个环境变量,或者是之前定义的属性。Microsoft.CSharp.targets位于C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727目录下,用记事本打开,查找“Name="CoreCompile"”,可以找到真正控制编译器运行的核心配置。其中$(xxx)表示一个之前定义的属性,@(xxx)表示之前定义的ItemGroup。可以发现,先前在SharedComponents.proj中定义的属性和Item,最后实际上都是给这一段CoreCompile用的。由这个target来控制csc编译器执行最终的编译。
在第一个PropertyGroup中添加一个属性:SrcDir,其值为“C:\Hello\private\HelloSolution\Shared\SharedComponents”,表示此项目源代码文件的位置。相应修改Compile项目组的Include属性为:
<ItemGroup>
<Compile Include="$(SrcDir)\Class1.cs" />
<Compile Include="$(SrcDir)\Properties\AssemblyInfo.cs" />
</ItemGroup>
回到HelloService.proj文件,依上所述,进行类似的修改。
注意ProjectReference这个ItemGroup,这一段将会被用来解析依赖关系,需要对Include属性做些修改。
最后形成的两个文件为:
SharedComponents.proj
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SrcDir>C:\Hello\private\HelloSolution\Shared\SharedComponents</SrcDir>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AssemblyName>Hello.SharedComponents</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<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)' == 'Release' ">
<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.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(SrcDir)\Class1.cs" />
<Compile Include="$(SrcDir)\Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
HelloService.proj
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SrcDir>C:\Hello\private\HelloSolution\Services\HelloService</SrcDir>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>WinExe</OutputType>
<AssemblyName>Hello.HelloService</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<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)' == 'Release' ">
<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.Data" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(SrcDir)\Service1.cs" />
<Compile Include="$(SrcDir)\Service1.Designer.cs" />
<Compile Include="$(SrcDir)\Program.cs" />
<Compile Include="$(SrcDir)\Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="SharedComponents.proj" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
最后参考上面的两个文件和MSDN上MSBuild的资料,新建HelloSite.proj文件:
<Project DefaultTargets="PrecompileWeb" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VirtualPath>/Hello</VirtualPath>
<PhysicalPath>C:\Hello\private\HelloSolution\Web\HelloSite\</PhysicalPath>
<TargetPath>Web</TargetPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugCompile>true</DebugCompile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugCompile>false</DebugCompile>
</PropertyGroup>
<Target Name="PrecompileWeb">
<AspNetCompiler
VirtualPath="$(VirtualPath)"
PhysicalPath="$(PhysicalPath)"
TargetPath="$(TargetPath)"
Force="true"
Debug="$(DebugCompile)"
Updateable="true" />
</Target>
</Project>
转到控制台,在C:\Hello\build目录下执行msbuild HelloService.proj,观察执行结果,发现MSBuild成功解析出HelloService引用了SharedComponent组件,并首先编译了被引用的组件,然后才编译目标组件。如图所示:
再执行msbuild HelloSite.proj,构建也成功了。
四、进一步完善
在这部分中,我们使用环境变量来替代长路径,把项目输出放到指定位置,将公用的属性配置放在一个引用文件里。由于在MSBuild系统中,系统环境变量和属性是通用的,因此这些目标并不难完成。
在C:\Hello\build目录中新建一个include.cmd文件。
@echo off
@set public=%inetroot%\public
@set private=%inetroot%\private
@set target=%inetroot%\target
@set product=%private%\HelloSolution
@set setup=%product%\Setup
@set wix=%public%\WiX
@set Platform=%PROCESSOR_ARCHITECTURE%
call "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sdkvars.bat"
在include.cmd中,我们指定了所需的环境变量,并调用了SDK的环境变量设置命令。
新建include.property文件,内容为:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<BaseIntermediateOutputPath>$(target)\</BaseIntermediateOutputPath>
<OutputPath>$(target)\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DebugCompile>true</DebugCompile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DebugCompile>false</DebugCompile>
</PropertyGroup>
</Project>
修改SharedComponents.proj:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="include.property" />
<PropertyGroup>
<SrcDir>$(product)\Shared\SharedComponents</SrcDir>
<OutputType>Library</OutputType>
<AssemblyName>Hello.SharedComponents</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(SrcDir)\Class1.cs" />
<Compile Include="$(SrcDir)\Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
修改HelloService.proj:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="include.property" />
<PropertyGroup>
<SrcDir>$(product)\Services\HelloService</SrcDir>
<OutputType>WinExe</OutputType>
<AssemblyName>Hello.HelloService</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(SrcDir)\Service1.cs" />
<Compile Include="$(SrcDir)\Service1.Designer.cs" />
<Compile Include="$(SrcDir)\Program.cs" />
<Compile Include="$(SrcDir)\Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="SharedComponents.proj" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
修改HelloSite.proj:
<Project DefaultTargets="PrecompileWeb" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="include.property" />
<PropertyGroup>
<VirtualPath>/Hello</VirtualPath>
<PhysicalPath>C:\Hello\private\HelloSolution\Web\HelloSite\</PhysicalPath>
<TargetPath>$( OutputPath)\Web</TargetPath>
</PropertyGroup>
<Target Name="PrecompileWeb">
<AspNetCompiler
VirtualPath="$(VirtualPath)"
PhysicalPath="$(PhysicalPath)"
TargetPath="$(TargetPath)"
Force="true"
Debug="$(DebugCompile)"
Updateable="true" />
</Target>
</Project>
在C:\Hello目录下新建一个build.proj文件:
<Project DefaultTargets="Compile"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<MSBuild Projects="build\HelloService.proj" />
<MSBuild Projects="build\HelloSite.proj" />
</Target>
</Project>
在C:\Hello目录中新建一个build.cmd文件:
@echo off
@set Configuration=Debug
msbuild build.proj /t:Build
@set Configuration=Release
msbuild build.proj /t:Build
在桌面上新建一个快捷方式,命名为“Hello”,Target设置为:
C:\WINDOWS\system32\cmd.exe /K set inetroot=C:\Hello&"C:\Hello\build\Include.cmd"
Start in设置为C:\Hello,Option中选上“QuickEdit mode”。
退出命令行,双击桌面上的Hello快捷方式,运行build,大约五秒钟后,整个方案就被成功构建了,所有的项目输出都在C:\Hello\target目录下。
五、Installer
VS.NET中可以新建一个安装项目,用来编译生成安装包,但是这种生成方式类似用IDE来build项目一样,不适于扩展,而且很难通过命令行来执行编译。
替代的方法是使用WiX toolset。WiX是Windows Installer XML的缩写,是微软的第一个开源项目,可以在SourceForge上下载。
在C:\Hello\private\HelloSolution目录下新建一个Setup目录。新建一个HelloService.wxs文件:
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
<Product Id="YOURGUID" Language="1033" Manufacturer="Hello Corporation" Name="HelloService" Version="1.0.0.0">
<Package Id="YOURGUID"
Description='Hello Service Windows Installer package'
Manufacturer='Hello Corporation' InstallerVersion='200' Compressed='yes' />
<Condition Message="You need to be an administrator to install this product.">
Privileged
</Condition>
<Condition Message='This product can only be installed on Windows Server 2003'>
VersionNT = 502
</Condition>
<Media Id="1" Cabinet='product.cab' EmbedCab='yes' />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='Hello' Name='Hello'>
<Directory Id='INSTALLDIR' Name='Service'>
<Component Id='MainExecutable' Guid=' YOURGUID '>
<File Id='HelloSvc' Name='Svc.exe' LongName='Hello.HelloService.exe' DiskId='1' src='$(env.target)\$(env.Platform)\$(env.Configuration)\Hello.HelloService.exe' Vital='yes' ProcessorArchitecture="x86" />
<ServiceInstall Id='ServiceInstall' DisplayName='Hello Service' Name='HelloService' ErrorControl='normal' Start='demand' Type='ownProcess' Vital='yes' Description="Hello service" />
<ServiceControl Id="ServiceUninstall" Name="HelloService" Stop="both" Remove="uninstall" Wait="yes" />
</Component>
<Component Id="ReferencedLib" Guid='YOURGUID'>
<File Id='SharedComponents' Name='shared.dll' LongName='Hello.SharedComponents.dll' DiskId='1' src='$(env.target)\$(env.Platform)\$(env.Configuration)\Hello.SharedComponents.dll' Vital='yes' ProcessorArchitecture="x86" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id='Complete' Level='1'>
<ComponentRef Id='MainExecutable' />
<ComponentRef Id='ReferencedLib' />
</Feature>
</Product>
</Wix>
其中的YOURGUID需要用一个自己生成的guid来代替,可以用C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\guidgen.exe来生成guid。
新建HelloSite.wxs文件:
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
<Product Id="YOURGUID" Language="1033" Manufacturer="Hello Corporation" Name="HelloSite" Version="1.0.0.0">
<Package Id="YOURGUID"
Description='Hello Site Windows Installer package'
Manufacturer='Hello Corporation' InstallerVersion='200' Compressed='yes' />
<Condition Message="You need to be an administrator to install this product.">
Privileged
</Condition>
<Condition Message='This product can only be installed on Windows Server 2003'>
VersionNT = 502
</Condition>
<Media Id="1" Cabinet='product.cab' EmbedCab='yes' />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='Hello' Name='Hello'>
<Directory Id='INSTALLDIR' Name='Site'>
<Component Id='Page' Guid='YOURGUID'>
<File Id='Default_aspx' Name='Default.asp' LongName='Default.aspx' DiskId='1' src='$(env.target)\$(env.Platform)\$(env.Configuration)\Web\Default.aspx' Vital='yes' />
</Component>
<Directory Id='binDir' Name='bin'>
<Component Id="ReferencedLib" Guid='YOURGUID'>
<File Id='AppCode' Name='App_Code.dll' LongName='App_Code.dll' DiskId='1' src='$(env.target)\$(env.Platform)\$(env.Configuration)\Web\bin\App_Code.dll' Vital='yes' ProcessorArchitecture="x86" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
<Component Id='SiteInstall' Guid='YOURGUID'>
<WebSite Id='DefaultWebSite' Description='Default Web Site' Directory='INSTALLDIR' DirProperties='webSiteProp'>
<WebAddress Id='AllUnassigned' Port='80' />
<WebApplication Id='HelloSite' Name='HelloSite' />
</WebSite>
</Component>
</Directory>
<Feature Id='Complete' Level='1'>
<ComponentRef Id='Page' />
<ComponentRef Id='ReferencedLib' />
<ComponentRef Id='SiteInstall' />
</Feature>
<WebDirProperties Id='webSiteProp' Script='yes' />
<CustomAction Id='ToggleASPNETVersion' ExeCommand='aspnet_regiis -s W3SVC/1/Root/' />
</Product>
</Wix>
注意HelloSite将在把Site程序安装在WebSite下,因此不要在你的关键机器上安装这个示例,并且安装HelloSite前要备份你的IIS设置。
修改build.cmd文件:
@echo off
@set Configuration=Debug
msbuild build.proj /t:Build
if not exist "%target%\%Platform%\%Configuration%\Setup" (mkdir "%target%\%Platform%\%Configuration%\Setup") ELSE (del "%target%\%Platform%\%Configuration%\Setup\*.*" /q)
%wix%\candle %setup%\HelloService.wxs -out "%target%\%Platform%\%Configuration%\Setup\\"
%wix%\light "%target%\%Platform%\%Configuration%\Setup\HelloService.wixobj" /out "%target%\%Platform%\%Configuration%\Setup\HelloService.msi"
%wix%\candle %setup%\HelloSite.wxs -out "%target%\%Platform%\%Configuration%\Setup\\"
%wix%\light "%target%\%Platform%\%Configuration%\Setup\HelloSite.wixobj" "%wix%\ca\sca.wixlib" /out "%target%\%Platform%\%Configuration%\Setup\HelloSite.msi"
@set Configuration=Release
msbuild build.proj /t:Build
if not exist "%target%\%Platform%\%Configuration%\Setup" (mkdir "%target%\%Platform%\%Configuration%\Setup") ELSE (del "%target%\%Platform%\%Configuration%\Setup\*.*" /q)
%wix%\candle %setup%\HelloService.wxs -out "%target%\%Platform%\%Configuration%\Setup\\"
%wix%\light "%target%\%Platform%\%Configuration%\Setup\HelloService.wixobj" /out "%target%\%Platform%\%Configuration%\Setup\HelloService.msi"
%wix%\candle %setup%\HelloSite.wxs -out "%target%\%Platform%\%Configuration%\Setup\\"
%wix%\light "%target%\%Platform%\%Configuration%\Setup\HelloSite.wixobj" "%wix%\ca\sca.wixlib" /out "%target%\%Platform%\%Configuration%\Setup\HelloSite.msi"
运行build,构建完成后,发现target目录中,MSI installer也被生成了。接下去运行
msiexec /i %target%\%Platform%\%Configuration%\Setup\HelloService.msi
C:\Program Files\Hello\Service目录中出现了安装好的文件。打开services.msc,找到“Hello Service”,试着运行一下。
运行msiexec /x %target%\%Platform%\%Configuration%\Setup\HelloService.msi卸载。
运行msiexec /i %target%\%Platform%\%Configuration%\Setup\HelloSite.msi安装Web程序。
运行msiexec /x %target%\%Platform%\%Configuration%\Setup\HelloSite.msi卸载。
六、自动化
最后一个任务就是实现自动化,每日定时构建。
在C:\Hello目录中新建一个DailyBuild.bat文件:
@echo off
@set inetroot=C:\Hello
call C:\Hello\build\Include.cmd
call C:\Hello\build.cmd
在Services.msc中enable “Task Scheduler”服务。在控制面板的“Scheduled Tasks”中,新建一个任务:Build Hello,指定其每天03:00AM运行C:\DailyBuild.bat。
右键点击这个task,选择运行,可以先看一下结果。
就这样,daily build的任务完全实现自动化了。
七、扩展
在示例方案中,由于MSI安装包都已经自动生成了,接下去能做的就更多了,例如实现自动部署,自动测试(BVT),自动report结果,等等。这些工作需要与tester合作,本文不再展开。
自动化流程是保持项目良好运作的关键,在微软公司,这一流程受到高度的重视,通常由developer manager直接负责。如果哪天出现了build break,那么developer在开始一天的coding之前,必须先找到昨天的build哪里出现了问题,先去修复,重新build,直到build成功为止,没有例外。
转自:http://blog.csdn.net/dz45693/article/details/6752653
============================
C:\Users\lx>msbuild.exe/?
Microsoft(R) 生成引擎版本 4.0.30319.1
[Microsoft .NET Framework 版本 4.0.30319.239]
版权所有(C) Microsoft Corporation 2007。保留所有权利。
语法: MSBuild.exe [选项] [项目文件]
描述: 在项目文件中生成指定的目标。如果
未指定项目文件,MSBuild 将搜索
当前工作目录来查找文件扩展名
以“proj”结尾的文件并使用该文件。
开关:
/target:<targets> 在此项目中生成这些目标。使用
分号或逗号分隔多个目标,或者分别指定
每个目标。(缩写: /t)
示例:
/target:Resources;Compile
/property:<n>=<v> 设置或重写这些项目级属性。<n> 是
属性名,<v> 为属性值。请使用
分号或逗号分隔多个属性,或者
分别指定每个属性。(缩写: /p)
示例:
/property:WarningLevel=2;OutDir=bin\Debug\
/maxcpucount[:n] 指定用于生成的最大
并发进程数。如果未使用开关,则使用的默认值
为 1。如果使用开关时不带值,
MSBuild 将最多使用计算机上的
处理器数。(缩写: /m[:n])
/toolsversion:<version>
要在生成过程中使用的 MSBuild 工具集
(任务、目标等) 的版本。此版本将重写
个别项目指定的版本。(缩写:
/tv)
示例:
/toolsversion:3.5
/verbosity:<level> 在事件日志中显示此级别的信息量。
可用的详细级别有: q[uiet]、 m[inimal]、
n[ormal]、d[etailed] 和 diag[nostic]。(缩写: /v)
示例:
/verbosity:quiet
/consoleloggerparameters:<parameters>
控制台记录器的参数。(缩写: /clp)
可用的参数有:
PerformanceSummary -- 显示在任务、目标和项目上
花费的时间。
Summary -- 结束时显示错误和警告的摘要。
NoSummary -- 结束时不显示错误和警告
的摘要。
ErrorsOnly -- 仅显示错误。
WarningsOnly -- 仅显示警告。
NoItemAndPropertyList -- 在开始生成每个项目时不显示
项和属性的列表。
ShowCommandLine -- 显示 TaskCommandLineEvent 消息
ShowTimestamp -- 将时间戳作为所有消息的前缀
显示。
ShowEventId -- 显示已开始事件、已完成事件和消息
的事件 ID。
ForceNoAlign -- 不将文本与控制台缓冲区的大小
匹配。
DisableConsoleColor -- 将默认控制台颜色
用于所有记录消息。
DisableMPLogging -- 在非多处理器
模式下运行时,禁用输出的多处理器
日志记录样式。
EnableMPLogging -- 即使在非多处理器
模式下运行,也启用多处理器
日志记录样式。默认情况下启用此日志记录样式。
Verbosity -- 重写此记录器的 /verbosity
设置。
示例:
/consoleloggerparameters:PerformanceSummary;NoSummary;
Verbosity=minimal
/noconsolelogger 禁用默认控制台记录器,并且不将事件
记录到控制台。(缩写: /noconlog)
/fileLogger[n] 将生成输出记录到文件中。默认情况下,
该文件在当前目录中,名称为
“msbuild[n].log”。所有节点中的事件合并到
单个日志中。fileLogger 的文件和
其他参数的位置可以通过添加
“/fileLoggerParameters[n]”开关来指定。
“n”(如果存在)可以为 1-9 的数字,允许最多附加
10 个文件记录器。(缩写: /fl[n])
/fileloggerparameters[n]:<parameters>
为文件记录器提供任何额外的参数。
存在此开关意味着
存在对应的 /filelogger[n] 开关。
“n”(如果存在)可以为 1-9 的数字。
任何分布式文件记录器也可以使用
/fileloggerparameters,具体可参阅 /distributedFileLogger 的
说明。
(缩写: /flp[n])
为控制台记录器列出的相同参数
可用。某些其他可用参数有:
LogFile -- 生成日志将写入其中的
日志文件的路径。
Append -- 确定是将生成日志附加到日志文件,
还是覆盖日志文件。如果设置此
开关,则会将生成日志附加到日志文件;
如果不设置此开关,则会覆盖
现有日志文件的内容。
默认值为不附加到日志文件。
Encoding -- 指定文件的编码,
例如,UTF-8、Unicode 或 ASCII
默认的详细级别为 Detailed。
示例:
/fileLoggerParameters:LogFile=MyLog.log;Append;
Verbosity=diagnostic;Encoding=UTF-8
/flp:Summary;Verbosity=minimal;LogFile=msbuild.sum
/flp1:warningsonly;logfile=msbuild.wrn
/flp2:errorsonly;logfile=msbuild.err
/distributedlogger:<central logger>*<forwarding logger>
使用此记录器来记录 MSBuild 中的事件,向每个节点
附加不同的记录器实例。若要指定
多个记录器,请分别指定每个记录器。
(缩写 /dl)
<logger> 语法为:
[<logger class>,]<logger assembly>[;<logger parameters>]
<logger class> 语法为:
[<partial or full namespace>.]<logger class name>
<logger assembly> 语法为:
{<assembly name>[,<strong name>] | <assembly file>}
<logger parameters> 是可选的,并且按键入的
形式原样传递给记录器。(缩写: /l)
示例:
/dl:XMLLogger,MyLogger,Version=1.0.2,Culture=neutral
/dl:MyLogger,C:\My.dll*ForwardingLogger,C:\Logger.dll
/distributedFileLogger
将生成输出记录到多个日志文件,每个 MSBuild 节点
一个日志文件。这些文件的初始位置为
当前目录。默认情况下,这些文件名为
“MSBuild<nodeid>.log”。可通过添加
“/fileLoggerParameters”开关来指定
这些文件的位置和 fileLogger 的其他参数。
如果日志文件名是通过 fileLoggerParameters
开关设置的,分布式记录器将使用 fileName 作为
模板并将节点 ID 附加到此 fileName
以便为每个节点创建一个日志文件。
/logger:<logger> 使用此记录器来记录 MSBuild 中的事件。若要指定
多个记录器,请分别指定每个记录器。
<logger> 语法为:
[<logger class>,]<logger assembly>[;<logger parameters>]
<logger class> 语法为:
[<partial or full namespace>.]<logger class name>
<logger assembly> 语法为:
{<assembly name>[,<strong name>] | <assembly file>}
<logger parameters> 是可选的,并按键入的
形式原样传递给记录器。(缩写: /l)
示例:
/logger:XMLLogger,MyLogger,Version=1.0.2,Culture=neutral
/logger:XMLLogger,C:\Loggers\MyLogger.dll;OutputAsHTML
/validate 依据默认架构验证项目。(缩写:
/val)
/validate:<schema> 依据指定的架构验证项目。 (缩写:
/val)
示例:
/validate:MyExtendedBuildSchema.xsd
/ignoreprojectextensions:<扩展名>
确定要生成的项目文件时要忽略的
扩展名的列表。使用分号或逗号来分隔
多个扩展名。
(缩写: /ignore)
示例:
/ignoreprojectextensions:.sln
/nodeReuse:<parameters>
允许或禁止重复使用 MSBuild 节点。
参数包括:
True -- 生成完成后节点将保留,
并且将由后面的生成重复使用(默认)
False -- 生成完成后节点将不会保留
(缩写: /nr)
示例:
/nr:true
/preprocess[:file]
通过嵌入将在生成过程中导入的
所有文件并标记其边界,
创建一个聚合的项目文件。这对于
了解导入什么文件、从何处导入以及
这些文件在生成中的构成
非常有用。默认情况下,输出将写入
控制台窗口。如果提供输出文件的路径,
则将改用该路径。
(缩写: /pp)
示例:
/pp:out.txt
/detailedsummary
在生成的结尾显示有关
所生成的配置以及如何向节点安排
这些配置的详细信息。
(缩写: /ds)
@<file> 从文本文件插入命令行设置。若要指定
多个响应文件,请分别指定每个响应
文件。
/noautoresponse 不自动包括 MSBuild.rsp 文件。(缩写:
/noautorsp)
/nologo 不显示启动版权标志和版权消息。
/version 仅显示版本信息。(缩写: /ver)
/help 显示此用法消息。(缩写: /? 或 /h)
示例:
MSBuild MyApp.sln /t:Rebuild /p:Configuration=Release
MSBuild MyApp.csproj /t:Clean
/p:Configuration=Debug;TargetFrameworkVersion=v3.5
- 使用MSBuild实现完整daily build流程
- 使用MSBuild实现完整daily build流程
- 使用MSBuild实现完整daily build流程
- 使用MSBuild实现完整daily build流程
- 使用MSBuild实现完整daily build流程 .
- 在.NET环境中实现每日构建(Daily Build)--ccnet,MSBuild篇
- 在.NET环境中实现每日构建(Daily Build)--ccnet,MSBuild篇
- 每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 利用VSTS实现Daily Build
- 使用ant进行Daily build
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CCNET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- 项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】
- linux curl命令详解
- 存储过程返回表
- google搜索语法,黑客必学
- Perl中某个值的真假判定
- C 语言常见问题集
- 使用MSBuild实现完整daily build流程 .
- 數學詞彙的英譯,寫文章,讀文獻必備 .
- The New C++ -- 变量(0)
- 深入研究java.lang.ThreadLocal类
- 使用Ajax.dll前台调用后台方法及错误示例
- 如何阅读源代码
- oracle 正则表达式
- JAVA面试题(二)
- 安装archlinux笔记