论坛首页 编程语言技术论坛

nant的典型应用——部署windows服务

浏览 2262 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-09-27   最后修改:2009-09-27
请首先浏览本文上一篇文章《nant的典型应用——部署web站点》

windows服务与web站点的区别在于nant构建脚本略有不同,大体上还是分为获取源代码、编译类库、编译windows服务几个步骤,不同的是安装/反安装服务步骤。示例构建脚本如下:
<?xml version="1.0" encoding="utf-8" ?>
<!-- 项目名称,只用于显示 -->
<project name="project_name" >
    <!-- 使用NAnt.Contrib,指定Contrib的路径 -->
    <loadtasks assembly="C:/OneClickDeploy/nantcontrib-0.86/NAnt.Contrib.Tasks.dll" />

    <!-- 源代码环境配置 -->
    <!-- 源代码输出路径,默认为输出到当前文件夹下的src文件夹 -->
    <property name="source.outdir" value="src"/>
    <!-- svn服务器地址 -->
    <property name="source.svn.path" value="svn://server/trunk/win_service0"/>
    <!-- svn用户名 -->
    <property name="source.svn.username" value="user"/>
    <!-- svn密码 -->
    <property name="source.svn.password" value="pass"/>

    <!--
    ***************************************************************************
    更新代码:如果代码已签出,执行update命令,否则执行checkout命令,一般不需要修改
    ***************************************************************************
    -->
    <target name="source">
        <if test="${directory::exists(source.outdir)}">
            <echo message="更新代码${source.svn.path}"/>
            <svn-update uri="${source.svn.path}" destination="${source.outdir}" username="${source.svn.username}" password="${source.svn.password}" verbose="false" />
        </if>
        <if test="${not directory::exists(source.outdir)}">
            <echo message="签出代码${source.svn.path}"/>
            <mkdir dir="${source.outdir}"/>
            <svn-checkout uri="${source.svn.path}" destination="${source.outdir}" username="${source.svn.username}" password="${source.svn.password}" verbose="false" cache-auth="false" />
        </if>
    </target>

    <!--
        编译代码“函数”
        compile.target:exe, winexe, library or module
        compile.assembly: 程序集
        compile.outdir: 输出路径
        complie.debug: true/false
     -->
    <target name="compile">
        <!-- 生成编译后的文件名 -->
        <if test="${compile.target=='library'}">
            <property name="compile.output" value="${compile.assembly}.dll"/>
        </if>
        <if test="${compile.target=='winexe'}">
            <property name="compile.output" value="${compile.assembly}.exe"/>
        </if>
        <csc target="${compile.target}" output="${path::combine(compile.outdir, compile.output)}" debug="${compile.debug}" optimize="true" verbose="false">
            <sources>
		<!-- 编译所有cs文件 -->
                <include name="${source.outdir}/${compile.assembly}/**/*.cs" />
            </sources>
            <references>
		<!-- 编译引用的dll文件,我将依赖的dll放到了svn://server/trunk/web0/Assembly文件夹下,所以这里需要制定引用Assembly下的所有dll文件 -->
                <include name="${source.outdir}/Assembly/**/*.dll" />
		<!-- 引用编译结果文件夹下的所有dll文件,一般来说类库项目之间也存在应用关系,基础类库编译完成后将编译结果dll存放compile.outdir文件夹下,编译业务类库时需要引用基础类库,因此需要引用compile.outdir下的所有dll -->
                <include name="${compile.outdir}/**/*.dll" />
		<!-- 排除引用的dll文件 -->
                <exclude name="${source.outdir}/Assembly/**/libmySQL.dll"/>
            </references>
            <resources>
		<!-- 嵌入的资源,需要将nhibernate映射文件作为嵌入的资源,编译到程序集中 -->
                <include name="${source.outdir}/${compile.assembly}/**/*.hbm.xml" />
            </resources>
        </csc>
    </target>

    <!--
    ***************************************************************************
    构建服务
    ***************************************************************************
    compile.debug:
    /debug [+/-] :当选用/debug +就会把创建.pdb文件,并把调试信息存储到里面;/debug -是一个缺省设置,就是不产生任何调试信息。
    /debug:[full/pdbonly] :当使用/debug:full就是创建缺省的调试信息,有点类似/debug+选项。/debug: pdbonly选项是创建.pdb文件,并且你只能使用源代码调试在调试工具里。
    compile.outdir:
    编译结果输出文件夹
    -->
    <property name="compile.debug" value="PdbOnly"/>
    <property name="compile.outdir" value="bin/sms"/>
    <target name="compile-sms" description="编译服务">
        <echo message="编译服务"/>
        <delete dir="${compile.outdir}" verbose="true" if="${directory::exists(compile.outdir)}" />
        <mkdir dir="${compile.outdir}"/>

        <property name="compile.assembly" value="Common"/>
        <property name="compile.target" value="library"/>
        <call target="compile" />

        <property name="compile.assembly" value="Business"/>
        <property name="compile.target" value="library"/>
        <call target="compile" />

        <property name="compile.assembly" value="Sms"/>
        <property name="compile.target" value="winexe"/>
        <call target="compile" />       
    </target>

    <!--
    ***************************************************************************
    部署服务
    ***************************************************************************
    -->
    <!-- 服务名称 -->
    <property name="service.name" value="WinServic"/>
    <!-- 服务运行路径 -->
    <property name="deploy.rundir" value="C:/WinServic"/>
    <target name="deploy-service" description="部署服务">
        <echo message="部署服务"/>

        <property name="service.path" value="${deploy.rundir}/${service.name}.exe"/>
        <!-- 卸载原服务 -->
        <if test="${file::exists(service.path)}">
            <exec program="installutil">
                <arg value="${service.path}" />
                <arg value="/u" />
                <arg value="/LogFile" />
            </exec>
        </if>
        <!-- 将编译结果复制到运行目录 -->
	<delete dir="${deploy.rundir}" if="${directory::exists(deploy.rundir)}" />
        <copy todir="${deploy.rundir}">
            <fileset basedir="${compile.outdir}">
                <include name="/**/*.*"/>
            </fileset>
        </copy>
        <!-- 复制配置文件 -->
        <copy todir="${deploy.rundir}">
            <fileset basedir="${source.outdir}/Sms">
                <include name="_config/**/*.*"/>
            </fileset>
        </copy>
        <!-- 复制依赖类库 -->
        <copy todir="${deploy.rundir}">
            <fileset basedir="${source.outdir}/Assembly">
                <include name="Antlr3.Runtime.dll" />
                <include name="Iesi.Collections.dll" />
                <include name="NHibernate.ByteCode.LinFu.dll" />
                <include name="NHibernate.dll" />
                <include name="LinFu.DynamicProxy.dll" />

                <include name="ImApiDotNet.dll" />
                <include name="libmySQL.dll" />

                <include name="log4net.dll" />
                <include name="Newtonsoft.Json.dll" />
            </fileset>
        </copy>
        <!--安装服务-->
        <exec program="installutil">
            <arg value="${service.path}" />
            <arg value="/LogFile" />
        </exec>
    </target>

    <!--
    ***************************************************************************
    启动服务
    ***************************************************************************
    -->
    <target name="run-service" description="启动服务">
        <echo message="启动服务"/>
        <!-- 启动服务 -->
        <servicecontroller action="Start" service="${service.name}" verbose="true" />
    </target>
</project>


使用
将上面的构建文件保存在任意文件夹下,如c:\deploy\service.build,并在这个文件夹下创建批处理脚本deploy-service.bat
path=C:\OneClickDeploy\nant-0.86;C:\OneClickDeploy\SlikSvn;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
nant -t:net-3.5 -buildfile:service.build source compile-service deploy-service run-service
pause

运行deploy-service.bat,首先会设置nant、svn、.net2.0 framework的路径,然后使用构建脚本进行部署:
1.更新源代码,首次运行会签出源代码
2.编译类库,示例中为Common、Business
3.编译服务代码
4.卸载原服务
5.将编译结果及依赖类库复制到运行目录
6.安装新服务
7.启动服务
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics