NAnt(3) – 各個擊破

一個 solution (方案)裡面可能不只一個 project,可能會有許多個。
以前,我會寫在同一個 build 檔案裡面,可是這樣會讓 build 變得很大而且難以維護。
NAnt可以讓你在 build 檔案裡面再去呼叫另外一個 build 檔案,如此一來,我們就可以讓各 build 檔案負責自己的事情,避免都放到同一個 build 檔案裡面了。
語法很簡單,利用 nant 這個 task 就可以達成:

<nant>
  <buildfiles>
    <include name="subdir/default.build" />
  </buildfiles>
</nant>

或者是偷懶一點,讓NAnt找到目前所在目錄下所有子目錄下的 build 檔案,然後進行 build

<nant>
  <buildfiles>
    <include name="**/default.build" />
  </buildfiles>
</nant>

如果,要執行的並不是 build 這個預設 target 的話,該怎麼辦呢?
你可以為 nant task 加上 target 這個 attribute,就行了。

<nant target=”clean”>….</nant>

最後,我們達到各個擊破的目的。

IronPython(1) – 安裝與執行 script

IronPython 是一個移植到 .Net framework 之上的 Python 分支,與其他 Python 最大的不同點就是他可以直接調用 .Net framework 內的所有類別庫。
安裝前的必要條件:

官方既下載網址:

目前最新的版本是 Beta 8,下載以後的安裝非常簡單,解開以後就可以了。
點選 IronPythonConsole.exe 就可以執行。
還記得以前的 BASIC 嗎?(我想大概很少人知道這種古早又親切的語言了)
你可以試著輸入

print “Hello world!”

或是

print 1+2

就可以快速看到你指令的輸出結果。
接著我們試試看執行官方提供的範例:

execfile( “tutorial/wfdemo.py” )

畫面會帶出一個視窗,你可以試試看在上面以滑鼠隨意點選一點,視窗會出現 “Hello” 的字樣。
讓我們將視窗關閉,按下 ctrl+z 離開 PythonConsole。
學習需要目標,我想試著用 IronPython 重寫 RSSMSN
甚至以後再用 Python + PyGTK(或 wxWidget) 來重寫看看。
明天的目標,讀取 RSS。
其他可以參考的資料:

錯誤 1935

在某些時候,安裝 .Net framework redistributable package 會失敗,出現如下的錯誤訊息:
錯誤 1935。An error occured during the installation of assembly component {….}. HRESULT: -2147319761.
netframeworkinstallation_1935_error
這時候你可以參考這位大老寫的剖析,相當清楚:Troubleshooting 1935 and 2908 errors during installation
我(或者應該說是我朋友)遇到的情況是用如下步驟就可解決:

  1. 將 %windir%\system32\mscoree.dll (在 Windows 98/me 上是 %windir%\system\mscoree.dll) 更名。
  2. 如果 %windir%\system32\urttemp 存在的話,刪除掉。(在 Windows 98/me 上是 %windir%\system\urttemp)
  3. 重新執行 .Net framework redistributable package 安裝程式

Porting

也許移植一個 .Net application 到其他平台上,並不如想像中容易。
正如 Java application 並不是 100% 的 run anywhere。
Mono專案的頭頭最近把Paint.NET移植到 Linux 的Mono上,你可以看看這篇他的文章:Porting Paint.NET to Mono
看到這個標題,我是很高興的,可是看完以後,發現移植的過程曲折離奇,其中的過程頗值得玩味。

資料繫結與巡覽

資料的繫結基本上都是靠 Controls.DataBindings,所以

text1.DataBindings.Add( new Binding(“Text”, ds, “customers.custNo”) );

就可以把 text1 這個控制項的 Text 屬性繫結到 ds.Tables[“customers”] 的 custNo 欄位上。
如果想要有一些處理與變化,那麼可以透過 Binding.Format 與 Binding.Parse:

Binding b=new Binding(“Text”, ds, “customers.custOrder.OrderAmount”);
b.Parse+=new ConvertEventHandler( currencyStringToDecimal); // currencyStringToDecimal 是自訂的
b.Format+=new ConvertEventHandler( DecimalToCurrencyString ); // DecimalToCurrencyString 也是…
text3.DataBindings.Add(b);

這表示在轉換控制項屬性到資料來源的時候,會透過這兩個事件作變化。
Parse 表示控制項到資料來源,而 Format 正好相反。
都繫結上了以後呢?我們可以透過 BindingManagerBase 來作巡覽。

BinderManagerBase bm = BindingContext[ dataset, “tablename” ];

此時可用 bm.Position 取得位置,bm.Current 取得當前的物件(如果資料來源是 datatable,那就是 DataRowView;若是陣列,那就是所指向的元素)
bm.Position+1 就是下一筆,反之則是上一筆。到了最後一筆的時候,bm.Position+1 以後仍然會是一樣。
那麼,位置移動的時候會觸發甚麼事件?PositionChanged。所以我們可以撰寫自己的處理事件,

PositionChanged+=new EventHandler( this.fmMain_PositionChanged )

不僅僅是 TextBox 可以作,只要有提供 DataBindings 屬性的控制項都可以。
把 Button 的 Text 屬性 Bind 到某資料來源的某欄,而 Enable 屬性又 Bind 到 某欄時,那麼當移動資料來源位置的時候,就可以讓 Button 的相關狀態自動改變了。
這讓我想到似乎可以作一些 state machine 的東西…

IDeserializationCallback.OnDeserialization()

在 deserialization 之後,需要做的一些處理可以寫在這裡。
.Net framework documentation 裡面的例子是以 Circle 類別作例子,圓的面積不 serialize,而是在 deserialize 之後再計算出來。

NAnt (2)

看完上一篇,你大概會想,要寫的 task 是如此之少,這真是太完美了。
但是對於笨Q來說,不幸的事情發生了…
笨Q 聽說 .Net 也移植到 Linux 上了,所以他想試試看把上篇的程式拿到 Linux 下編譯,於是笨 Q 安裝了 Mono。接著安裝 NAnt。
同樣他下載了 NAnt, 並且解開,放到 /opt/nant 下。
再把整個專案複製到 Linux 下,並且修改了一下 build 檔的內容,由

<property name=”nant.settings.currentframework” value=”net-1.1″/>

改為

<property name=”nant.settings.currentframework” value=”mono-1.0″/>

讓 NAnt 在建立專案前自動把編譯環境切換為 mono。
接著輸入
$mono /opt/nant/bin/NAnt.exe
這時只見 NAnt 很不爭氣的吐了一句:

Invalid element <solution>. Unknown task or datatype

笨Q 只能流淚默默接受這個事實,他知道必須自己學著寫 target。


一個 NAnt 的 build 檔案其實是一個 XML 檔案,最基本的元素是 project,project 則是由 target 與 property 組成的,而 target 則是由許多的 task 組成的。
所以一個空的 build 檔案是長這個樣子:
<?xml version="1.0"?>
<project name="dnsedu" default=“build”>
  <property name=“nant.settings.currentframework” value=“net-1.1″/>
  <target name=“build” description="Default build target" depends="dnsedu">
  </target>
</project>
那麼 target 裡面有哪些 task 可以用呢?你可以參考官方網站的這裡
裡面真的很多 task,除了基本編譯(csc, vbc, cl, al, ilasm, resgen)之外,他還有 copy, cvs, mail, nunit …等等的 task,絕對可以讓你組合出你想要的東西。
要改寫上篇的 build(我假設你用 c#),我們會用到 csc、mkdir 這兩個主要的 task。
以下是改寫好的 build 檔案
<project name="your_project" default="build">
  <property name="nant.settings.currentframework" value="mono-1.0"/>
  <property name="debug" value="false"/>
  <target name="build">
    <mkdir dir="bin" unless="${directory::exists(‘bin’)}" />
    <csc target="winexe" output="bin/your_project.exe" debug="${debug}">
      <sources>
        <include name="*.cs"/>
      </sources>
      <references>
        <include name="System.Drawing.dll" />
        <include name="System.Data.dll" />
        <include name="System.Windows.Forms.dll"/>
      </references>
      <resources>
        <include name="*.resx"/>
      </resources>
    </csc>
  </target>
</project>
mkdir task 這邊我使用了 unless,意思是 if not,所以意思就是當目錄不存在的時候,就建立一個。這裡判斷目錄是否存在的函數是 NAnt 內建的,想知道有哪些函數可用,可以參考NAnt官方網站的這邊
csc task 裡面,則需要指定輸出類型(target),輸出檔名(output)以及要不要包含除錯資訊(debug)。
夾在 <csc></csc> 裡面的,就是指定你 c# 程式,所引用(或參考)到的組件以及所使用的資源檔。
很簡單,對吧~
這就是最基本的囉,下次我們來談談 web 應用程式的部份。

NAnt (1)

在 .Net 2.0 以前,如果不使用 IDE 來建立專案,而想要直接在命令列打個指令就可以建立的話,你有 3 種選擇:

  1. 批次檔
  2. Makefile
  3. NAnt

.Net 2.0 之後,多了一種選擇:msbuild。
這一系列文章主要是討論 NAnt,可是為甚麼要用 NAnt ? 又為甚麼要用 NAnt ??
簡單來說,爽。
如果要講跨平台,用 Makefile、msbuild (mono 已經搞了一個工具叫 xbuild,與 msbuild 相容) 都可以跨平台。
如果要講簡單,我個人是覺得 Makefile 比他還簡單。
如果要講功能,msbuild 也不遑多讓。
所以我說,就是一個爽。
Ant 是 Java 平台上一個極為重要的工具,而NAnt 最早是想把 Ant 移植到 .Net 上,所以才叫做 NAnt。
官方網址在:http://nant.sourceforge.net
下載 .zip 檔案以後,解開就可以用了,沒什麼特別的安裝步驟,即便是 Linux 也一樣。
我假設你解開以後會放到 c:\tools 下,並更名為 nant 。
廢話不多說了,直接從第一個實例開始。
我想一般人還是很習慣用 Visual Studio.Net 來開發吧。
所以,先隨便建立一個 Windows form 專案,確定它可以編譯。(或者你也可以用你手頭上的專案來試試)
接著在該專案目錄下,建立一個文字檔,並命名為 your_project.build (是了,your_project 你得自己替換一下。)
裡面放置如下內容:

<?xml version=”1.0″?>
<project name=”your_project” default=”build”>
<property name=”nant.settings.currentframework” value=”net-1.1″/>
<target name=”build”>
<solution configuration=”release” solutionfile=”your_project.sln” />
</target>
</project>

存檔以後,進入命令列模式,輸入

c:\tools\nant\bin\nant

這樣就大功告成了。
為甚麼可以這麼簡單?因為 NAnt 在 0.85.2296 以後已經添加了解析 Visual Studio 專案檔的能力,所以 build 檔裡面就只要用 solution 這個 task 就可以搞定了。
但是很可惜的是還不支援 Visual Studio 2005,即便是最新的版本也還沒看到蹤跡。

TheServerside.Net 訪談 Miguel De Icaza

Q and A with Miguel "Mono Man" De Icaza

這是一篇訪談,對象是Mono專案的 leader,裡面提到很多關於 Mono 的現況與未來發展.
稍微整理一下我看到的:

  1. 1.2 beta 1 將會在四月釋出,最主要要完成的是 Windows form 1.1 的部份.
  2. vb.net compiler, 實做狀況不佳,因為 Linuxer 都對 c# 比較可接受,但是你可以先在 windows 編譯好 il (assembly)再拿到 mono 上用.
  3. 有討論到關於 object pascal / iron python / ruby 的一些事情.
  4. 對 .Net 2.0 的支援, c# 2.0 compiler 都已經完備了, 目前少的是 2.0 的類別庫. 在1.2之後,他們會排定開發順序.