source:http://www.cnblogs.com/dragon/archive/2005/07/29/203189.html
在.NET環境中實現每日構建--NAnt篇
前言 關於每日構建這個話題,也已經有很多很好的文章討論了。本文的寫作過程中也參考了這些文章。本文之所以繼續這個題目,是因爲在查閱了網上的資源後,發現沒有一個比較通用的過程。所以本文就主要討論了利用NAnt構建一個通用日編譯的方案。利用這個方案,日編譯的維護者可以不需要對每個要編譯的方案都要做很多維護。只要定義一個屬性文件就可以了。 關鍵詞: Daily Build, NAnt 1. 簡介
1.1. 每日構建的優點:
每日構建(Daily Build)也可稱爲持續集成(Continuous Integration),強調完全自動化的、可重複的創建過程,其中包括每天運行多次的自動化測試。每日構建的作用日益顯得重要。它讓開發者可以每天進行系統集成,從而減少了開發過程中的集成問題。
持續集成可以減少集成階段"捉蟲"消耗的時間,從而最終提高生產力。它使得絕大多數bug在引入的同一天就可以被發現。而且,由於一天之中發生變動的部分並不多,所以可以很快找到出錯的位置。
1.2. 每日構建完成的任務
實現自動化每日構建需要做以下幾部分的工作:
l 使創建過程完全自動化,讓任何人都可以只輸入一條命令就完成系統的創建。
l 使測試完全自動化,讓任何人都可以只輸入一條命令就運行一套完整的系統測試。
l 確保所有人都可以得到最新、最好的可執行文件。
2. 每日構建所使用的工具
在.NET環境下建立每日構建可以使用一系列開源工具:
Nant: 完成代碼的自動編譯,自動運行測試工具。http://nant.sourceforge.net/builds/
NantContrib:自動從源碼庫中獲取源代碼。http://nantcontrib.sourceforge.net/nightly/builds/
NUnit2Report:將NUnit測試工具產生的XML報告轉換爲HTML報告形式。http://NUnit2Report.sourceforge.net
VSS:Visual Source Safe,微軟源碼管理工具
Draco.NET: 用於自動檢測VSS中源代碼變動情況,調用Nant完成自動編譯
http://sourceforge.net/projects/draconet/
下載所需的工具後,按照如下步驟進行安裝:
在服務器上安裝VSS源碼管理工具
安裝下載的Draco Server 和 Draco Web,修改安裝後的Draco Web目錄下的web.config文件,設置正確的Draco Server安裝路徑
將NAnt、NAntContrib、NUnit2Report壓縮包解壓,將三個Bin目錄中的內容複製到一個公用目錄,比如D:/DailyBuildTools,然後將該路徑加入系統的Path路徑列表中,具體爲“控制面板-〉系統屬性-〉環境變量-〉Path”
3. NAnt自動腳本
NAnt腳本實現了每日構建的主體功能,它具體分爲下面幾部分
l 定義每日構建所需的一些環境變量,比如從VSS上下載的源碼的保存目錄,發佈目錄等
l 清除舊的代碼並從VSS源碼庫中下載最新源代碼
l 編譯源代碼並運行測試代碼集
l 將編譯後的目標代碼拷貝到發佈目錄進行發佈
爲了儘可能少的改動NAnt的腳本文件,簡化日常維護的工作量,我們把一些對所有項目都基本相同的過程抽取出來,如環境變量定義,清除舊代碼獲取新代碼,編譯源代碼,對目標代碼進行發佈的過程都可以寫成通用的腳本,而一個具體項目的每日構建腳本則調用通用過程完成
本文采取的目錄體系如下所示:
D:/DailyBuild/
<project1>/Source:存放<project1>源代碼的目錄
<project1>/Build:存放<project1>編譯後的目標代碼的目錄
<project1>/Publish:存放<project1>的WEB發佈文件的目錄
<project1>/log:存放<project1>的日誌文件
3.1. Nant的基礎知識
l Nant腳本代碼文件的基本結構
<?xml version="1.0" encoding="gb2312"?>
<project name="Projects" default="prebuild">
<target name="prebuild" depends="namecheck,clean " description="…">
……
</target>
<target name="namecheck" >
……
</target>
</project>
說明:encoding="gb2312"使得腳本文件可以支持中文
<project>標籤定義了項目屬性,一個腳本文件只能有一個項目定義
default="prebuild"說明該項目缺省從prebuild任務開始執行
<target>標籤定義了一項任務,任務是Nant腳本具體執行動作的最小單元
depends="namecheck,clean "說明該任務執行前需要namecheck和clean任務先執行
description描述了該任務的一些說明性信息
l 定義變量
<property name="<變量名>" value="$<變量值>"/>
如上所示,定義變量使用<property>標籤,name屬性定義了變量的名稱,value屬性定義變量的值,其中name屬性可以使用字母、數字、點號、下劃線等符號,而value屬性可以使用字符串或是已經定義的變量,Nant內建的函數等,
要使用已經定義的變量,可以用${<變量名>},要使用內建函數,可以使用${<函數名稱>}
如: <property name="solution.basedir" value="${core.basedir}/${solution.name}"/>
使用了已定義變量core.basedir和solution.name來定義變量solution.basedir;
<property name="curdir" value="${directory::get-current-directory()}"/>
使用了NAnt內建函數directory::get-current-directory()來定義curdir變量
定義環境變量的腳本代碼寫在Common。Config文件裏
主要有以下幾類信息的定義:
l 每日構建所在的根目錄
<property name="curdir" value="${directory::get-current-directory()}"/>
<property name="core.basedir" value="${curdir}"/>
說明:${directory::get-current-directory()}內建函數獲取當前文件所在路徑信息
l 被編譯的解決方案的目錄結構,和前面提到的目錄體系一致
<property name="solution.basedir" value="${core.basedir}/${solution.name}"/>
<property name="solution.source" value="${solution.basedir}/source"/>
<property name="solution.build" value="${solution.basedir}/build"/>
<property name="solution.log" value="${solution.basedir}/log"/>
說明:以上代碼是定義了要編譯的解決方案的目錄結構信息,其中${solution.name}是由外部傳入的解決方案的名稱,後面的代碼將根據該名稱在日編譯的根目錄下生成和solution.name指定的名稱同名的目錄,並在該目錄下生成source,buld,log等子目錄
l VSS源代碼管理系統的基本信息
<!--vss數據庫登錄信息-->
<property name="vss.username" value="autobuild"/>
<property name="vss.password" value="autobuild"/>
<!--vss數據庫所在的位置-->
<property name="vss.dbpath" value="//10.136.238.231/vss/srcsafe.ini"/>
<!--vss中工程的根目錄-->
<property name="vss.basepath" value="$/"/>
說明:定義了和VSS源碼管理系統相關的一些信息,其中VSS數據庫所在位置可以是網絡路徑,也可以是本地路徑
l <編譯時的一些參數
<!--編譯版本號-->
<property name="build.number" value="1.0"/>
<!--決定編譯是Debug版本還是Release版本-->
<property name="build.configuration" value="Release"/>
3.3. 建立目錄結構,獲取源代碼
腳本代碼寫在CheckSource.build.xml文件裏
l 包含在Common.config文件裏定義的公共變量
<include buildfile="common.config"/>
l 檢查是否存在solution.name變量
<target name="namecheck" description="檢查solution.name變量是否設置">
<!--檢查解決方案名稱是否已經定義-->
<ifnot test="${property::exists('solution.name')}">
<fail message="未定義解決方案名稱solution.name"/>
</ifnot>
<!--去掉可能的空格字符-->
<property name="solution.name" value="${string::trim(solution.name)}"/>
<!--檢查solution.name變量是否爲空字符-->
<if test="${string::get-length(solution.name)==0}">
<fail message="未定義解決方案的名稱solution.name"/>
</if>
</target>
說明:${property::exists('<變量名>')}是NAnt內建函數,用於測試某變量是否存在
${string::get-length(<字符串變量>)==0}測試字符串的長度是否爲0
<ifnot test=<邏輯表達式> … </ifnot>:如果test表達式值爲假,執行<ifnot>標籤內的代碼
<if test=<邏輯表達式> … </if>:如果test表達式值爲假,執行<if>標籤內的代碼
l 建立解決方案的目錄結構
<target name="clean" depends="namecheck" description="移除舊目錄,建立新目錄">
<!--刪除舊的解決方案代碼所在目錄-->
<delete dir="${solution.basedir}" failοnerrοr="false"/>
<!--重新建立目錄-->
<mkdir dir="${solution.basedir}/" failοnerrοr="false"/>
<mkdir dir="${solution.source}" failοnerrοr="false"/>
<mkdir dir="${solution.build}" failοnerrοr="false"/>
<mkdir dir="${solution.log}" failοnerrοr="false"/>
</target>
說明:delete和mkdir標籤內的failonerror屬性表示即使操作文件夾的過程中出現了錯誤,也忽略錯誤向下執行
l 獲取源代碼:
從VSS上獲取解決方案<solution.name>的源代碼
<target name="getsourcecode">
<!--檢查從VSS上下載解決方案的路徑是否設定-->
<!-- 如果不定義vss.projectpath,則缺省爲solution.name -->
<ifnot test="${property::exists('vss.projectpath')}">
<property name="vss.projectpath" value="${solution.name}"/>
</ifnot>
<vssget
user="${vss.username}"
password="${vss.password}"
localpath="${solution.source}"
recursive="true"
replace="true"
dbpath="${vss.dbpath}"
path="${vss.basepath}${vss.projectpath}"
/>
</target>
說明:<vssget>標籤是NAntContrib的語法,用來從VSS源碼管理器上下載源代碼,user和password屬性表示登錄VSS服務器的信息;Localpath屬性是指下載的源代碼存放的路徑;recursive="true"表示遞歸獲取代碼;replace="true"表示如果本地有重複文件,則進行覆蓋;dbpath定義VSS的srcsafe.ini文件的路徑信息,包括srcsafe.ini文件名;path定義了要獲取的源代碼在VSS數據庫中的路徑,一般都是以$/爲根目錄。
3.4. 編譯源代碼
l 編譯命令
編譯解決方案的命令爲
<solution solutionfile="…" configuration="…" outputdir="…">
<webmap>
<map url="… " path="…"/>
<map url="… " path="…"/>
</webmap>
</solution>
其中solutionfile屬性表明了要編譯的解決方案文件的路徑信息,即以"sln"爲擴展名的文件,
configuration屬性表明要編譯的是發行版還是調試版,取值爲"Release"或"Debug"
outputdir表明了編譯後的動態鏈接庫或可執行文件存放的目錄
solution中的嵌套標籤<webmap>用於當解決方案含有WEB項目的情況,有幾個WEB項目,就有幾項<map>標籤,map標籤中的url屬性爲WEB項目的*.csproj文件的WEB路徑,path則爲該*.csproj文件所在磁盤上的物理路徑,例如,解決方案中有WEB項目exam,則map標籤爲 <map url="http://localhost/exam/exam.csproj" path="c:/exam/exam.csproj"
l 根據解決方案名稱獲取解決方案文件的路徑信息
<target name="build" description="編譯解決方案">
<!-- 查找解決方案文件名 -->
<foreach item="File" property="filename">
<in>
<items>
<include name="**/${solution.name}.sln"/>
</items>
</in>
<do>
<!--根據文件名設置解決方案的名稱-->
<property name="solution.file" value="${filename}"/>
</do>
</foreach>
說明:<foreach>標籤是NAnt中處理循環的命令,item="File"說明foreach進行循環處理的對象是文件,<include>中的name變量表示要查找的文件信息,"**/"表示查找路徑包括子目錄。Foreach的屬性property="<變量名>"表示查找到的文件路徑信息保存在該變量中,可以在<do>標籤中引用.foreach每查找到一項符合條件的Item,都會執行<do>標籤中的代碼,以上代碼執行的結果就是查找到指定名稱的解決方案文件,供後面編譯代碼使用
l 獲取解決方案中WEB項目的路徑信息
如果解決方案中含有WEB項目,則其編譯命令和不含WEB項目的解決方案編譯有所區別,所以要區別對待。如果解決方案含有多個WEB項目,則可以讓用戶將多個WEB項目的名稱放在一個變量中,如solution.webprojects,以逗號或分號或空格做分隔符。然後將項目名稱分別提取出來,根據Web項目的個數決定solution命令的形式,代碼如下
<!--將solution.webprojects中用",",";"或" "分隔的Web工程名提取出來,
分別設爲webproject1,webproject2 -->
<if test="${property::exists('solution.webprojects')}">
<foreach item="String" in="${solution.webprojects}" delim=";, " property="project">
<if test="${property::exists('webproject1')}">
<property name="webproject2" value="${project}"/>
</if>
<ifnot test="${property::exists('webproject1')}">
<property name="webproject1" value="${project}"/>
</ifnot>
</foreach>
</if>
以上代碼中foreach標籤的屬性item="String" in="${solution.webprojects}" delim=";, " property="project"表明循環對象是字符串,對in所代表的字符串
如果設定solution.webprojects="webprj1;webprj2”,則以上代碼執行的結果是定義了兩個變量webproject1 ="webproj1"和webproject2 ="webproj2"
l 查找WEB工程名
根據前面從solution.webprojects中提取出來的webproj1和webproj2變量,查找該WEB工程的文件名
<!-- 查找WEB工程文件名 -->
<if test="${property::exists('webproject1')}">
<echo message="test ${webproject1}" />
<foreach item="File" property="filename">
<in>
<items>
<include name="**/${webproject1}.csproj"/>
</items>
</in>
<do>
<!--根據Web項目的名稱獲取Web項目文件路徑,可以處理兩個Web項目的情況-->
<echo message="WebProject file=${filename}"/>
<property name="webproject1.file" value="${filename}"/>
</do>
</foreach>
</if>
同理可以處理存在第二個WEB工程項目的情況,設置webproject2.file變量
l 編譯解決方案
最後是編譯解決方案,分別根據無WEB項目,有2個WEB項目,有一個WEB項目的三種情況處理
下面僅列出有兩個WEB項目的情況
<!-- 存在2個Web工程 -->
<if test="${property::exists('webproject2')}">
<solution
solutionfile="${solution.file}"
configuration="${build.configuration}"
outputdir="${solution.build}"
>
<webmap>
<map
url="http://localhost/${webproject1}/${webproject1}.csproj"
path="${webproject1.file}"
/>
<map
url="http://localhost/${webproject2}/${webproject2}.csproj"
path="${webproject2.file}"
/>
</webmap>
</solution>
</if>
3.5. 運行測試代碼
l 測試命令
NAnt中關於測試的命令是<NUnit2>標籤
<nunit2>
<formatter type="Xml" usefile="true"
extension=".xml" outputdir="…"
/>
<test assemblyname="…" haltonfailure="false" />
</nunit2>
說明:<formatter>標籤中,type="Xml"表明了根據測試結果生成XML結構化信息,usefile="true"表明使用文件保存測試結果,extension=".xml"表明生成的文件擴展名爲xml,outputdir指出了文件將被保存到哪個目錄
Test標籤中的assemblyname表明了被測試的dll程序集的路徑信息,haltonfailure="false"表明即使測試沒有通過仍然繼續執行腳本文件
這樣在測試命令完成後,會在outputdir指出的目錄下生成一個XML形式的報告文件,爲了增加測試結果的可讀性,可以使用另一個工具NUnit2Report,將測試結果轉換爲直觀的HTML文件。具體命令如下
<nunit2report out="<文件名>" todir="<輸出目錄" >
<fileset>
<includes name="<文件匹配符>" />
</fileset>
</nunit2report>
說明:includes標籤用來搜索符合條件的XML文件,轉換出來的HTML文件保存爲out指出的文件名,todir指出了HTML文件將保存的目錄信息
<if test="${property::exists('solution.testprojects')}">
<foreach item="String" in="${solution.testprojects}" delim=";, " property="project">
<property name="testfile" value="${solution.build}/${project}.dll"/>
<nunit2>
<formatter type="Xml" usefile="true"
extension=".xml" outputdir="${solution.build}" />
<test assemblyname="${testfile}" haltonfailure="false" />
</nunit2>
<nunit2report out="${project}.html" todir="${solution.log}" >
<fileset>
<includes name="${solution.build}/*.xml" />
</fileset>
</nunit2report>
</foreach>
</if>
3.6. 進行WEB發佈
WEB發佈主要針對有WEB工程項目的解決方案,其實現原理爲利用NAnt的拷貝命令,將WEB工程下除了源代碼,資源代碼,VSS信息文件外的其他文件和編譯後的程序集拷貝到發佈目錄,最後設置WEB虛擬路徑以供WEB訪問的過程。
設置WEB虛擬路徑的命令爲
<mkiisdir dirpath="<物理路徑>" vdirname="<虛擬路徑>"/>
說明:設WEB項目發佈在C:/Intepub/wwwroot/Exam,訪問該WEB項目用地址http://127.0.0.1/Example/default.aspx,則<物理路徑>爲"C:/Intepub/wwwroot/Exam",虛擬路徑爲"Example"(此處略去詳細代碼)。
評論
字體是不是小了一號,看起來有些不習慣
回覆 引用 查看
你可以下載我的示例代碼,參考這篇文章看,這樣可能看起來容易些
回覆 引用 查看
這個字體實在難受阿,老大。
回覆 引用 查看
小小的建議:作者可以在標題里加上Daily Build, 可以使搜索方便一些。
回覆 引用 查看
Java的世界是一個分裂的世界,而.net的世界是一個全面統一的世界。幾乎沒有人使用vs.net以外的開發工具,包括使用MS提供的Web Matrix的都幾乎沒有。
使用“每日構建”或者單元測試必須依賴IDE的支持,所以最聰明的作法還是等待MS來提供,而不是依賴一些垃圾產品,例如NAnt、NUnit或者Log4Net這樣完全不考慮.Net中的一些特殊性的、純粹從Java移植過來的東西。幾乎可以肯定地講,這些NXXX的東西是不可能成功的,完全沒有可能象Java世界中一樣成爲標準。學習它們只是浪費時間和精力,甚至污染頭腦中的純潔。
回覆 引用 查看
謝謝你的建議,已採納!
To 雙魚座:
你的觀點太極端了,我不敢苟同,呵呵!
每日構建這個概念不是與IDE脫節,即使是微軟,也是在使用每日構建的。另外我並不覺得NAnt是“垃圾”,應該說他是個很優秀的開源項目。而且我個人認爲,我們應該鼓勵多樣性和創造性。如果沒有NAnt,NUnit,Log4net這樣的優秀開源項目,微軟會不會考慮在他的產品里加入這些相應的特性,也是個值得懷疑的問題。一個典型的例子就是,自從Netscape公司被微軟用瀏覽器綁定的方法擠垮後,微軟在瀏覽器軟件上基本就沒有大的創新了。而Firefox流行起來後,微軟又準備研發下一版新的瀏覽器了。所以如果等待微軟主動提供,估計你會把眼睛望穿的。
Anyway,這個問題是仁者見仁,智者見智,每個人都有自己的觀點。所以我覺得這個問題深入討論下去也沒什麼意義。所以,就讓這個話題到此爲止吧。
回覆 引用 查看
回覆 引用
我還沒有看到vs2005中的msunit,我無權評論。但是我對NUnit是有權評論的。雖然我目前爲止一直用NUnit做單元測試,但是我已經可以肯定NUnit不可能象JUnit一樣成爲標準。
我只能猜測一下。象NUnit這樣的東西,MS應該會做得更合理一些,至少不會將TestFixtureAttribute、TestAttribute和Assert這些在擴展中必須用到的類型封閉了。因爲這樣的封閉不會對NUnit GUI帶來半點好處。你應該知道,JUnit成功的原因並不是JUnit這樣一個簡單的程序,而是一種標準、一種體系。JUnit吸引衆多開發者的原因是因爲JUnit有了數不清的擴充,而NUnit根本沒有提供任何擴充的可能。
微軟或者說世界上任何一家大的軟件公司都會從開源汲取營養,這是肯定的,但我更肯定不會是從NXXXX這些垃圾產品。
我不知道你從我100%肯定JUnit、Ant、Hibernate、Log4J的同時,又100%否定NUnit、NAnt、NHibernate、Log4Net,到底是覺得我開放還是覺得我保守?
回覆 引用 查看
我以爲你的觀點才過於主觀。MS是不是會吸收NUnit、NAnt、Log4Net這些有人認爲是垃圾的東西,我覺得你是無法確定的。你怎麼就認爲MS不是從JUnit、Ant和Log4J獲取的營養呢?畢竟所有在.net中實現的java中的開源項目比在java中的實現相差一大截是一個顯而易見的客觀事實。每日構建在某些情況下是需要的。但現在在.net中不具備你所謂的“每日構建”的環境。每日構建是一種開發模式的特徵,而RAD是另外一種開發模式的特徵。
不明白你爲什麼不能接受別人對你的話題進行評論。難道這樣纔是開放而不是保守嗎?
回覆 引用 查看
我想對一個問題,每個人有每個人的看法,這是很正常的。我覺得我們可以發表自己的觀點,也沒必要強求別人接受自己的觀點,求同存異是王道,呵呵。
我想我也沒有“不能接受別人對你的話題進行評論”。我只是在這個問題上有不同觀點而已,而不同意你的觀點並不等於不能接受你的評論,是麼?但是,請大家注意,在我的版面上是絕對禁止相互之間進行人身攻擊的!相互間有不同的觀點碰撞,這是正常的,甚至這種碰撞比較激烈,這也是允許的。但請大家保持對彼此的相互尊重(以上這段話並不針對任何人)。我這裏歡迎任何技術方面的討論
回覆 引用 查看
回覆 引用 查看
“所以我覺得這個問題深入討論下去也沒什麼意義。所以,就讓這個話題到此爲止吧。”
在網上好象大多數都是這樣的。因爲我提出了不同的意見,令別人不快,所以急於停止話題。事實上我也只是說明我的觀點,從來沒有強迫別人來接受,不是嗎?相反我倒真的希望能夠有機會領教哪位高手舉出NXXXX有哪些閃光點。
回覆 引用 查看
回覆 引用 查看
“所以我覺得這個問題深入討論下去也沒什麼意義。所以,就讓這個話題到此爲止吧。”--如果這句話讓你感到不快,我向你道歉。我說這句話沒有其他意思,只是覺得像這樣的討論很難達到一個共識,討論到後來也不會有什麼結果,所以才這樣說。並不是針對你的評論。
回覆 引用 查看
你說的應該是NXXXX的本意,的確,XXXX的思想值得推崇。遺憾的是,NXXXX不僅沒有很好地實現,反而對理解和發揚XXXX的思想造成破壞。並且,這種現象不是偶然,而是普遍存在。我渴望在.net的世界裏出現真正體現XXXX思想的東西,相信大多數人都和我一樣渴望。但是NXXXX的每一個項目都令我極端地失望。
@sema:
很難達到共識的東西很多,但是我不認爲不能達到共識就不要去討論,至少這不是一種Open的態度。不過我還是必須尊重你的態度,我退出你這個話題的討論。
回覆 引用 查看
我沒有不願你討論,我只是發表我個人的觀點而已。當然我的觀點不一定完全正確,你可以僅把我當作一個話題的參與者。
回覆 引用 查看
象你這樣的人,在這裏有很多,我看到過很多象你這樣的回覆。這和我想象中的博客園是不一樣的。一篇文章,它哪怕只給一個人帶來了幫助,那就夠了。不需要象你這樣的人來顛覆它,你知道你說的那些根本就是沒意義的。也許你這樣的人在技術方面真的很好,那麼我希望你不是在這裏說一些無意義的話,而是爲。net多做出些實質的東西。
另外,你知道sema爲什麼說這個問題到此爲止嗎?是因爲你的回覆用詞不當,請你在技術方面無限提高的同時,別忘了本,中國是個謙遜的民族,而從你的言語中看不出來。
回覆 引用
請別這樣說雙魚座,我想每個人都有自己的觀點。作爲技術方面的看法,我覺得不同的觀點是可以保留的。我不願意繼續就這個問題討論下去,是擔心討論到後來就成了口水仗,沒有實質性的結果。我只有這個意思,沒有更多的意思。
我想雙魚座也只是表達了他對N****的看法,也沒有反對我發這樣的文章來幫助一些需要這方面知識的人。大家之間討論問題,如果傷了和氣,就是我不願意看到的了。
謝謝大家的參與!
回覆 引用 查看
在前段時間,也包括最近,園子裏有很多關於nxxx的介紹,或者是需要用的nxxx的一些opensource的東西,我的感覺是兩個字:飽和。
對於寫文章的人,是爲了表達自己的觀點態度,但是對看文章的人,如果瞭解甚至熟悉作者的文章內容的話,可以有自己的不同觀點,但是很多想來了解作者所述的內容的人,作者的文章對他們有一定導向作用,當園子裏的“個人觀點”鋪天蓋地的時候,就是要有一些爭論,與其只講怎麼應用,不如就該內容是否有價值做些大膽的爭論,亦能加深旁人的印象,有能讓參與者鞏固自己的認識。
雙魚座算起來是前輩了,當然我不反對他的這種表達方式並不是因爲這個,只是經常看到他的一些所謂激進的回覆,偶爾象強心劑一樣讓我對一些老套的文章有了新的認識,併產生關注的興趣。
回覆 引用 查看
我的解決方案裏只有一個winform的項目,項目裏引用了word,在編譯時出現一個錯誤:找不到文件或程序集名稱“Microsoft.Office.Interop.Word”,或找不到它的一個依賴項。
如果我去掉word引用,編譯就沒問題。請問像這種引用com組件的情況下,build文件應該怎麼寫?
回覆 引用
回覆 引用 查看
發完了前面的消息纔看到原來是你啊!你寫的太客氣了,什麼“您”啊,搞得我還以爲認錯人了。呵呵!
回覆 引用 查看
回覆 引用
我最近在研究這塊
看了你的文章對我的幫助很大
現在正在藉助你這文章的幫助在做一些的事例
可能還會運到一些困難
不知道sema你最近有沒有空
我遇到的問題發出來 可不可以幫助我下
回覆 引用 查看
我只能說盡量了。去年換了工作,現在轉做SAP了。而且這個題目我也是一年半前做過一些研究。好長時間不摸,有些生疏了。不到之處還請諒解!
回覆 引用 查看
首先謝謝你對我的留言回覆,我借用了你的例子,現在就是在<nunit2>這個標籤中做測試的時候他所編譯的.xml文件沒有在我指定的目錄下生成。我的代碼如下
<?xml version="1.0" encoding="gb2312"?>
<project name="Projects" default="test">
<include buildfile="common.config"/>
<target name="test" description="查找並測試代碼">
<if test="${property::exists('solution.testprojects')}">
<foreach item="String" in="${solution.testprojects}" delim=";, " property="project">
<property name="testfile" value="F:/fw/DailyBuild/bin/netshop.dll"/>
<nunit2>
<formatter type="Xml" usefile="true" extension=".xml" outputdir="f:/fw/NUnit/" />
<test assemblyname="${testfile}" tonfailure="false" />
</nunit2>
<nunit2report out="netshop.html" todir="F:/fw/DailyBuild/NUnit" >
<fileset>
<includes name="netshop/*.xml" />
</fileset>
</nunit2report>
</foreach>
</if>
</target>
</project>
請你抽空的時候幫我看看 謝謝~~
回覆 引用 查看
回覆 引用
回覆 引用
回覆 引用
回覆 引用 查看
回覆 引用
回覆 引用
有問題想請教大家
回覆 引用 查看
問:NANT,有沒有支持MSBUID的方案呢?
回覆 引用
回覆 引用 查看
回覆 引用
回覆 引用 查看