查看單個文章
舊 2004-06-21, 02:15 PM   #1
mic64
註冊會員
 
mic64 的頭像
榮譽勳章
UID - 582
在線等級: 級別:16 | 在線時長:330小時 | 升級還需:27小時級別:16 | 在線時長:330小時 | 升級還需:27小時級別:16 | 在線時長:330小時 | 升級還需:27小時級別:16 | 在線時長:330小時 | 升級還需:27小時級別:16 | 在線時長:330小時 | 升級還需:27小時級別:16 | 在線時長:330小時 | 升級還需:27小時
註冊日期: 2002-12-06
VIP期限: 2007-04
住址: MIB總部
文章: 412
精華: 0
現金: 499 金幣
資產: 499 金幣
預設 利用Script語言撰寫COM物件

毫無疑問地,科技的發展正在急遽進步中。從下面這個故事,你可以看到活生生的例子:大概一年前,一個名為scriptlet的小演員首次在Dynamic HTML (DHTML)這個大舞台中首次登場演出。它們本身是HTML網頁,但運作模式確像真正的元件,它們提供屬性與方法,供其他程式使用。Scriptlet也能夠觸發系統事件,發出專屬的通知。根據這些特性我們可以斷定,Scriptlet將是網站元件化的過程中,最重大的進展。由於Scriptlet的出現,撰寫可重複使用的HTML程式碼不再是問題。你可以準備一個HTML元件,例如資料表格,盡可能放入多個參數,然後在網頁中任何需要的地方,加入一行程式來呼叫這個元件。唯一比較可能遇到的問題是瀏覽器支援性的問題,因為Scriptlet目前仍受限於只能用在Microsoft Internet Explorer 4.0以後的版本。

但是就像我前面提過的,科技正急遽進步中。過去被視為革命性且功能強大的解決方案,在今日都將被更普通、更具威力的解決方案所取代。這正是發生在Scriptlet身上的情況。就在Scriptlet問世的幾個月之後-Scriptlet被改成更具意義的Dynamic HTML scriptlet-它們原本只是附在Internet Explorer 4.0的一個新技術。然而好景不長,隨後又出現了新技術,稱為XML scriptlet,或就簡稱scriptlet。XML scriptlet的出現,大幅取代了Dynamic HTML所扮演的角色。

結果是,當我們要設計用於Web-based的個案的元件時,我們擁有兩種選擇:DHTML scriptlet與XML scriptlet。兩者並非彼此互斥,但每一個都擁有專屬的定義與格式。而且,至少在原則上,你可以在網站應用程式的client端與server端自由地使用這兩種Scriptlet。

DHTML vs. XML Scriptlet


讓我們來研究看看,為何這兩種技術會被廣泛採用,而且就像硬幣的兩面,缺一不可。就用途來看,軟體元件的完整定義應該是「一個自我包含、可程式化、可重複使用、可輕易插入應用程式中、獨立於程式語言之上的程式區段」。它們提供屬性與方法供應用程式使用,也可以觸發事件,同時透過名字和/或ID作為意義明確的識別代號。

DHTML Scriptle與XML Scriptlet兩者顯然都符合前述的定義。不同之處在於XML scriptlet完全以COM為基礎,而DHTML scriptlet則是採用完全不同的實作方式,部分則是模擬COM的特性。表格1概要地列出DHTML scriptlet與XML scriptlet如何實作出軟體元件所提供的共同特性。2
表格1. DHTML scriptlet與XML scriptlet如何實作軟體元件所提供的共同特性

特性 DHTML scriptlet XML scriptlet
可程式化界面 透過JavaScript函式 型態函式庫3
建立機制 一個稱為public_description的JavaScript函式 DllGetClassObject()函式
方法與屬性 public_description方法 COM Automation介面
事件4 DHTML的視窗,外部物件 COM的連結指標界面
開發的程式語言 HTML與script XML
物件識別 檔案名稱與MIME形式5 ProgID與CLSID
註冊 不需要。它能夠自己提出唯一的(System registry) 利用系統註冊檔案名稱
放置於網頁上 <OBJECT> 標籤加上MIME形式 <OBJECT>標籤加上CLASSID屬性6
加入普通的應用程式中 透過已經安裝完成的Microsoft ActiveX 控制項 直接透過安裝(installation)

DHTML scriptlet所提供的可程式化界面,其實就是一組屬於動態定義的JavaScript函式的方法(method):

<script language="JavaScript">
public_description = new CreateScriptlet;
function CreateHotImage() {
this.get_Property1;
this.put_Property1;
this.Method1;
}
另一方面,XML scriptlet的可程式化界面,被編譯成一般的COM型態函式庫。而且,函式會透過COM的介面進行分類。DHTML scriptlet讓你可以擁有一個單一的、全部包含(all-encompassing)的界面,而XML scriptlet則不受此限制。另外DHTML scriptlet本身會提供一個唯一的檔案名稱作為識別代號,所以不需要任何的註冊程序。當檔案建立,或被下載到你的電腦上時,就已經可以被使用,不需其他額外的程序。

在普通的應用程式中安插scriptlet還是反應出兩者在結構上的不同。因為DHTML scriptlet在本質上是一份網頁,所以最低限度你需要一個WebBrowser控制項(例如,Microsoft Visual Basic中提供的控制項)來安插DHTML scriptlet。然而,更理想的方法是利用特殊的scriptlet控制項,該控制項可以從Microsoft Scripting Technologies Web網站上得到,網址是7 http://msdn.microsoft.com/scripting/ 。因為XML scriptlet的運作模式完全跟COM物件一樣,所以你所需要做的只是設定scriptlet的實例,好讓該scriptlet能夠在普通的應用程式中運作。例如,在Visual Basic中,可能使用的程式碼如下:

Dim o As Object
Set o = CreateObject( "XML.Scriptlet" )
當然,「XML.Scriptlet」利用的是元件的ProgID。

DHTML scriptlet是一種利用HTML元素組合而成,含有使用者介面(UI)的元件。這些HTML元素包括了影像、表格、文字與超連結...等等。你可以利用script程式來統籌這些元素,而且利用Dynamic HTML的物件模型來賦予元件的生命週期與互動性。

XML scriptlet為那些以script為基礎的元件提供了更多的基本底層架構,著重於元件的行為特性,而不是花俏的使用者介面。

XML Scriptlet的架構8


對於XML scriptlet,一個簡潔有力的定義如下:「利用script語言所寫成的COM元件」。 你可以利用MicrosoftJScript 開發軟體、Microsoft Visual Basic Scripting Edition (VBScript),以及任何支援ActiveX scripting-compliant解析器(parser)的程式語言來撰寫XML scriptlet。我想,此時你想問的不外乎「魔法在哪裡?」或者是「那些COM的要素,如class factories、IUnknown,,被藏在哪裡?」等問題吧!

嗯,當然,我會解釋這些問題。然而,有趣的是,XML scriptlet是起源於COM+的基本原理:將使用者認識的元件行為與COM必要的底層分隔開來。COM+會提供一個系統的執行時期模組,負責完成一些預設的實作工作,如class代理程式、動態連結函式庫(DLL)的註冊、reference計數、dispatching,與連結點的處理、界面查詢...等,讓我們能夠更輕鬆地撰寫元件。換言之,XML scriptlet擁有執行時期連結的能力,也可以運用中繼資料(metadata)來描述物件,就像COM+所做的一樣。而你必須負責的工作有:

&reg;利用中繼資料(metadata)來描述你實作的界面。

&reg;撰寫程式來完成界面所提供的各項功能。

這些原則完全適用於圖1裡面所介紹的XML scriptlet架構。其中scriptlet檔是由三個主要部分組成:註冊資訊、界面對應,以及script程式碼。除了註冊資訊是常見於一般的COM元件之外,另外兩部分就是中繼資料(metadata)與程式碼。9



圖1. XML scriptlet架構

Client端應用程式永遠是面對scriptlet的執行時期模組-一個名為scrobj.dll的DLL。這個DLL提供了管線(plumbing),讓認識COM的client端應用程式能夠將XML scriptlet當成是真正且具效率的二進位COM元件使用。例如,執行時期模組可能會顯示一個IDispatch界面,讓client端應用程式使用。任何由client端發出的函式呼叫會導致執行時期呼叫適當的界面處理程式,以執行適當的Jscript或VBScript程式。在這種方法中,我們實際上利用最簡單的script語言撰寫了一個COM物件。執行時期模組的所有可供外部呼叫的界面都是利用XML程式碼寫成。這些外部界面必須由一個預先定義的 界面處理程式 (interface handler)負責處理。(稍後筆者將會介紹有關界面處理程式的相關知識。)每一個XML scriptlet都是利用scrobj.dll作為其真正的in-process server模組。

其實XML scriptlet就是一個沒有使用者界面,且不依賴任何物件模型的Automation物件。如果想要加上使用者界面,那麼你必須改用DHTML scriptlet。

一般對於XML scriptlet的使用方式,都是利用XML scriptlet來建構小型、有效率,且可重複使用的軟體元件,讓server端利用ASP網頁使用這些元件來進行程式開發。然而,在本文後面,筆者將教導你一種使用這類元件的令人嘆服方式。10
XML Scriptlet的檔案


XML scriptlet是一個ASCII檔,副檔名為.sct,是利用三個主要標籤組合而成:<registration>、<implements> 與 <script>。其中<registration>標籤包含了與元件識別相關的所有資訊。除了這些資訊,還有ProgID與CLSID。兩者都是COM的共同元素,分別由長度為128個位元的字串組成,且都可以用來建立元件的實體。ProgID與CLSID都是獨一無二的識別代號。通常,CLSID是以一連串的十六進位數字組成,中間以破折號分隔,利用大括號將整個字串包圍。當開發XML scriptlet時,通常會加上一段敘述與版本代號以利閱讀與識別。而XML scriptlet全部的程式碼都是放置在一組<scriptlet>標籤內,如下面這個範例所示:

<scriptlet>
<registration
Description="This is a bare-bones Scriptlet."
ProgID="BareBones.Scriptlet"
Version="1.00"
ClassID="{00000000-1010-1010-83d1-f49604c10010}"
>
</registration>
</scriptlet>
最有趣的部分是接下來的<implements>區段。在這裡你將定義元件準備提供的界面。換言之,每一個<implements>標籤相當於一個COM的界面,client端將會透過QueryInterface這個界面來取得並呼叫它。根據這個階段的技術規格,你只能為那些擁有界面處理程式的界面加入實作的程式碼,其他的界面則不行。簡單的說,就是界面並不是藉著CLSID或界面名字(如ISomething)作為識別。相反地,界面是透過一個稱為Type的屬性被識別。Type屬性的內容很像關鍵字,負責告訴執行時期的模組應該呼叫哪個COM server,以處理client端所發出的要求。界面也有一個ID屬性,它的用途是讓你在程式中可以利用這個ID屬性來代表物件。當界面處理程式擁有自己專屬的物件模型時,這個ID就相當有用。<implements>標籤裡頭的內容是根據界面提供的特性而定。這個內容也會受到界面上的特定處理程式所建立的層級所影響。下面介紹的就是一個傳統的<implements>標籤區段。

<implements type="Automation" id="dispatcher">
<method name="Hello">
<parameter name=numHELLO />
</method>
</implements>
最後,<script>標籤組內包含了要實作界面功能的所有程式碼。例如,前面介紹過的scriptlet擁有一個像下面這樣的<script>標籤區段,其中方法的功能只是簡單地將特定數目的「Hello」字串傳回:

<script language="JavaScript">
function Hello (numHello) {
var strText = "";
for( i=0; i<numHello; i++ )
strText += strText + "Hello";
return strText;
}
</script>11
界面處理程式


界面處理程式是一個in-process COM server,負責為界面提供一組標準的實作方式。它是XML scriptlet中最重要的特性。而且,整個界面處理程式連結起來就列出了該scriptlet所提供的所有COM界面。

然而,界面處理程式還是有其限制。首先,你不能定義自訂的界面。再者,尚未有合法的方式可以製作你個人專屬的界面處理程式。目前你所能撰寫的XML scriptlet大多都是Automation server。而隨著Internet Explorer 5.0的問世,系統提供的界面處理程式將會大量增加,包括事件、行為與ASP程式的相關支援。

Automation處理程式負責處理Automation的界面。尤其是,它實作了一個IDispatchEx事件處理程式。IDispatchEx負責處理觸發事件所需的所有工作,就是一個連結點界面。如同你將見到的,在界面處理程式與界面之間的關係是一對多的。




圖2. XML scriptlet的運作模式

每一個界面處理程式都是被設計支援某個界面(或某組界面),在scriptlet與client端運作,讓兩者能夠進行通信,如圖2所示。然而,從scriptlet的程式中,你只能與展示了Automation界面的物件通訊。所以,界面處理程式有時必須展露本身的物件模型,來幫助scriptlet的使用。在圖2中有介紹這種做法。按照這種方法,界面處理程式所扮演的角色將改變成:界面處理程式是一個實作了一個或多個COM界面的物件,另有很多輔助讓這些函式能夠輕易地從script程式中被呼叫與使用。此外,所有的處理程式在<implements>標籤中需要不同的XML標籤以提供正確的資訊。12
Automation處理程式


Automation處理裝置包含了一組由某個scriptlet所展露的屬性與方法。而真正負責分派任務的引擎被藏在執行時期模組中。其語法規定你必須透過<method>與<property>標籤來指定各項元素。每個方法必須要有一個名字,還要有一個內部名字(如果可能的話),用以確定真正實作方法的script程序(procedure)。如果你省略了內部名字,那麼系統會假設有一個與方法相同名稱的程序。而屬性可以以全域(global)變數的方式展露,或者你可以定義特定的程序來負責讀取與寫入屬性值。利用這種方法,你就可以將屬性定義成唯讀或唯寫。

<method name="Method1" internalName="DoMethod1" />
<property name="Prop1" internalName="m_Prop1" />
前面的範例中展示了方法(Method1)的宣告被定義於函式DoMethod1中,而且Prop1屬性則以m_Prop1變數來表示。而internalName屬性則是選擇性的。m_Prop1變數是一個全域變數,用來儲存屬性值。或者,你也可以將它改寫成如下所示:

<property name="Prop1">
<get internalName="DoGetProp1" />
<put />
</property>
其中Prop1屬性是透過一個名為DoGetProp1的函式進行讀取,透過put_Prop1函式作寫入。put_Prop1是一個遵守標準命名規則的函式。這種命名規則是想要讓讀取的動作透過名為get_的函式後面接著屬性名字所組成的程序完成。當然,所有必要的函式,包括方法與屬性,都必須在<script>標籤的區段中進行實作。

請注意,利用這種方式來定義方法與屬性是一種以高階的方式來看待Automation。所有COM所必須的工作,從這些工作到分派界面等都是由Automation處理程式來負責進行。13
連結點(Connection Points)


如果你想讓scriptlet能夠觸發事件,你必須將它對應到事件處理程式。事件處理程式提供了必要的COM底層機制,透過IConnectionPoint與IconnectionPointContainer兩個界面的標準實作。筆者之前曾介紹過,在scriptlet與處理程序之間有一個額外的Automation程式的中間層,它是用來處理事件。事件處理程式的設計是為了提供一種服務-從script程式中觸發事件。雖然就觀念上而言相當簡單,但實際上在內部還是有許多工作需要處理程式來負責。它必須顯示一個向外的界面,好讓client端能夠sink,進而當事件發生時,client端能夠找到註冊過的sink。這個過程需要簡化。事實上,事件處理程式物件會展露一個fireEvent方法,讓scriptlet的事件能夠讓外界知道:

<implements type="Event" id="MyScriptlet">
<event name="BeginWork" />
<event name="WorkCompleted" />
</implements>
這個範例介紹一個scriptlet,該scriptlet提供兩個事件-BeginWork與WorkCompleted。COM會將事件與一個名為dispid的dispatch識別代號結合。然後這個識別代號(ID)會被編譯到型態函式庫中,供client使用以連結事件。通常,用來為scriptlet產生型態函式庫的模組(參閱下一個程式範例)會提供一個自動給定的dispid,好讓scriptlet能夠用來提供事件。然而,藉著加入一個dispid屬性你可以自己來決定哪個dispid要指定給哪個事件。

<event name="BeginWork" dispid=65 />
下面是事件真正從程式中被觸發的範例:

<script language="JScript">
function DoWork() {
MyScriptlet.fireEvent("BeginWork")

// place code here
MyScriptlet.fireEvent("WorkCompleted")
}
</script>14
如果你在事件處理程式中使用default屬性,那麼在事件處理程式宣告中就不用加上MyScriptlet字首。

Internet Explorer 5.0 Behavior


目前最新定義出來的第三種界面處理程式就是Internet Explorer 5.0的behavior。或許你會猜,它們是否只在Internet Explorer 5.0中被支援。事實上,它們只是XML scriptlet實作了一組特殊的Internet Explorer 5.0的界面,如IElementBehaviorXxx。Behavior的觀念其實很簡單。它們的主要目的就是利用script程式將HTML的標籤轉換成串接樣式表(CSS)中的樣式。利用這種方法,當你為一個或一組元素定義樣式時,你可以直接指定某個「behavior」,就像指定圖形的相關屬性,如字型與色彩一樣。

Behavior是一個定義什麼是CSS類別的元素可以執行的元件。例如,如果你需要scriptlet能夠處理DHTML的事件,或者是提供額外的屬性或方法,那麼你可以撰寫一個behavior。另外behavior也可以讓網頁的原始程式碼更具可讀性,並藉著動態地清理網頁內的script程式來加強相關的維護工作。同時,這樣做並不會限制你利用HTML元素,與其他附加特性的能力-包括標準的元素如<img>或「自訂的」元素像是DHTML scriptlet。

一個Internet Explorer 5.0 behavior必須實作behavior的處理程式。如果需要的話,它也可以實作Automation處理程式或界面處理程式。Behavior需要Automation以便能夠適當地處理使用各項元素的HTML程式的屬性。例如,假設我們擁有一個針對<img>標籤的behavior,並希望它能夠根據屬性值顯示不同的影像。其屬性可能是色彩深度。所以在HTML網頁中其程式碼可能如下:

<img id="one" class="colorimg" src="" color="16" child="one">
在colorimg類別中會有下面這樣的定義:15
<style>
.colorimg {behavior: url(colorimg.sct)}
</style>
Scriptlet colorimg.sct中包含一個針對colorimg類別中所有元素的behavior。裡面的程式碼應該看起來像這樣:

<scriptlet>
<implements type="behavior" />
<implements type="automation" />
<property name="color" />
<property name="child" />
</implements>

<script language="JavaScript">
attachEvent( "onload", event_onload );

function event_onload() {
document.all(child).src = child + color +
".gif";
}
</script>
</scriptlet>
這個scriptlet提供了一個behavior、一個擁有兩個屬性:color與child的Automation界面。Scriptlet本身貼附到網頁會觸發的onload事件中。這是透過一個attachEvent函式來達成。該函式是Internet Explorer 5 DHTML的物件模型特有的函式。而要反應這個onload事件,scriptlet會決定要在<img>標籤中顯示哪張影像。影像的名字是由標籤的名字決定,透過child屬性傳入,另外還有色彩的值,是由color屬性傳入。

<img id="one" class="colorimg" src="" color="16" child="one">
在這個範例中,影像的檔名為one16.gif。

Scriptlet與Client端應用程式16


因為XML scriptlet是真正的COM物件,所以可以在任何與COM相容的開發環境中使用這些scriptlet,因為COM的開發語言是獨立的:從Visual Basic到Delphi,從Microsoft Visual C++ 到ASP等的程式都可以。

現在讓我們看看client端應用程式與XML scriptlet之間如何發生互動。要建立一個XML scriptlet的實體,client端不需使用別種新方法,只要使用平常建立COM物件實體的方法即可。因此,在Visual Basic中你可以這樣呼叫:

Dim o As Object
Set o = CreateObject("BareBones.Scriptlet")
o.Hello 4
Set o = Nothing
CreateObject的背後,在client端與COM server端之間有一個普通的通信往來。在前面的程式區段中,client端會要求IDispatch界面及一個名為Hello的方法。而呼叫CreateObject之後所得的檔案為scrobj.dll,為一個執行時期模組。它用來作為client端與Automation界面處理程式之間的proxy。它會傳給client端一個由scriptlet實作界面的參照,但它並不會實作這些界面。相反地,它依賴那些稱為界面處理程式的特殊模組。

在Visual Basic的程式中,我們使用CreateObject與late binding。如果你擁有scriptlet的型態函式庫,那麼你就可以採用early binding。

Scriptlet的型態函式庫


型態函式庫是一個檔案,收集了透過COM元件所實作界面的所有相關資訊。當然也包括了XML scriptlet所提供界面的相關資訊。型態函式庫的建立並不是必要的,但是它非常有用,特別是當你在Visual Basic中使用元件時。例如,Microsoft IntelliSense(r)的技術便非常倚賴型態函式庫,以便顯示出某個物件所提供的所有屬性與方法的資訊。提到Visual Basic,藉著參考scriptlet的型態函式庫,你可以為scriptlet加上一個WithEvent關鍵字的宣告,這樣就可以與scriptlet所提供的事件建立關聯。17
要替XML scriptlet產生型態函式庫有兩種方法。你可以利用離線的方式,藉著利用滑鼠右鍵點選.sct檔案,並選擇右邊的指令。或者是,你可以利用程式撰寫的方式來產生,如下所示:

Set oTL = CreateObject("Scriptlet.GenerateTypeLib")
oTL.AddURL "c:\MyDir\myScriptlet.sct"
oTL.Write
oTL.Reset
這段程式在任何狀況下都可執行-在另一個以產生型態函式庫為目的的元件,或甚至是在scriptlet本身於註冊階段要執行一次都有用。如果你希望程式在註冊scriptlet時能夠運作,你可在<registration>標籤中加入一個<script>標籤,並定義一個稱為register的函式:

<registration
Description="This is a bare-bones Scriptlet."
ProgID="BareBones.Scriptlet"
Version="1.00"
ClassID="{00000000-1010-1010-83d1-f49604c10010}"

<script language="VBScript">
Function register()
' create type library

End Function
Function unregister()
' do what you need to do
End Function
</script>
</registration>
而在解除註冊的過程中,會執行一個unregister函式。

型態函式庫中可以包含多個scriptlet的資訊。在這種情況下,會重複地呼叫AddURL方法,後面接著不同的檔名。檢視位於 http://msdn.microsoft.com/scripting/18 的scriptlet文件,以獲得更多有關在產生型態函式庫時你能夠選擇的選項。

XML Scriptlet與Windows Scripting Host


XML scriptlet是一個由XML與script程式所組成的COM物件,在執行時期環境的最上層運作。執行時期會處理所有的工作並讓scriptlet能夠以真正COM物件的形式出現在client端,就像利用Microsoft Visual J++ 、 Microsoft Visual FoxPro與Microsoft Visual Basic所產生的COM物件一樣的運作方式。你可以把XML scriptlet當成是一個安靜且不帶使用者界面的軟體模組,分別運作於client(DHTML元件與behavior)與server(ASP網頁)兩端。此外,在client端我們可以利用一個稱為DHTML scriptlets的不同scriptlet。DHTML scriptlets是一個可程式化且可崁入的DHTML網頁。

Microsoft Windows Scripting Host (WSH)的出現開啟了一個XML scriptlet的新領域。如果你正在撰寫WSH applet,你通常會使用VBScript或JScript。與批次檔相較,WSH applet的確是更容易且更具威力。但是在可重複使用的問題上,XML scriptlet還是最好的選擇。

讓我們看個範例,該範例提供了一個實際觀察XML scriptlet的機會。我們的目標是將所有曾於特定日期做過修改的檔案通通列舉於某個特定的目錄下。若是利用C或C++來進行並不難,但若是利用script程式來負責就有點麻煩了。然而,重要的是程式必須是可重複使用的。程式範例1示範了完成這項工作的scriptlet,檔名為filefinder.sct。其progID是FileFinder,這是一個展露兩個方法的Automation scriptlet。

FindFirstFileByDate( pathSpec, date )
FindNextFileByDate()
指定了目錄名稱與檢查日期,函式就會將搜索結果符合的部分放到那個目錄中。若是要列舉目錄的內容,我們可以利用一種由Internet Explorer 4.0所引進的shell物件:19
Set m_Shell = CreateObject( "Shell.Application" )
Set m_Folder = m_Shell.NameSpace( m_PathSpec )
m_Folder物件現在包含了所有目錄項目的集合。剩下的工作就是將修改日期與條件日期做個比較。NameSpace方法會傳回一個目錄型態的物件,這是一個FolderItem物件的集合。shell物件模型的相關文件是放在Internet Client SDK Help檔案中。

範例程式會連續地掃描列出的檔案以進行比對。比對的部分是透過VBScript的一個DateDiff函式:

FileDate = m_Folder.Items.Item(m_Index).ModifyDate
d = DateDiff( "d", FileDate, m_Date )
DateDiff函式會傳回兩者日期的不同,以天數表示。這個值是以「d」參數來進行測量。Scriptlet首先會將目錄物件做初始化,然後開始依據列表的順序進行移動,搜尋所有符合使用者條件的檔案。你可以呼叫FindFirstFileByDate來將引擎初始化,並取得第一個檔名。然後會為檔案連續呼叫FindFirstFileByDate。

觀察程式範例1,你將注意到在檔案的起始部分有一行奇怪的程式,看起來像這樣:

<?scriptlet validate="true" error="true" debug="true"?> 。20

這行程式的用途僅僅是為了除錯用。如果發生錯誤,scripting的執行時期引擎大概只會顯示一個訊息。但是這行程式則會產生一個較具描述性且精確的文字,來記錄每一個錯誤。

第二個會讓你好奇的部分是<![CDATA[ ... ]]>圍住了所有的script程式碼。如同我曾說過的,它保證在script程式中任何可能引發錯誤的字元將不會造成XML解析器的混淆。利用這種括號將讓你免於討厭的與無法預期的錯誤。若是不加上該行,可能會產生難以預料的錯誤,像我就曾經遇到註解程式發生錯誤。參考下一段會告訴你原因。就目前來看,記住CDATA區段是完全與<?XML version="1.0"?>在一起的,並出現在XML檔案的起始部分。

程式範例2中示範了如何在WSH script中利用FileFinder物件的優點。使用VBScript所寫成的簡單script擁有一行指令行,內含兩個需要的參數:目錄的路徑與日期。這兩個參數預設值是C槽與目前日期。

如同FileFinder元件所示範的,透過XML scriptlet最終你將能夠撰寫可重複使用的程式,就像撰寫批次檔一樣簡單。

XML的編譯


到目前為止,我們已經學到XML scriptlet主要是XML檔案,而有關其語言的部分呢?XML是一種比HTML來得較嚴格的語言。當你在撰寫scriptlet時,通常最常犯的錯誤是:

&reg;21使用錯誤的標籤。

&reg;使用特殊的XML字元像是「<」與「>」作其他用途。(例如,在script程式中)

&reg;當指定標籤屬性的內容時忘記使用引號。

這些是不會出現在HTML網頁中的錯誤。預設的情況下,執行時期會解析XML scriptlet檔案以確定它是否為一個HTML檔案。換言之,它讓你能夠遵循前面三個規定,這些規定在HTML中是正常的,但在XML中則不是。另一方面,這麼鬆散的語法在你將程式移植到XML 1.0相容的編輯器中一定會造成問題。最近,筆者在使用內建於Internet Explorer 4.0中的XML物件模型時就曾經碰到這樣的問題。筆者撰寫了一個ActiveX控制項,作用是當作普通的XML解析器,能夠將XML檔案中的內容安排成樹狀結構的瀏覽情況。(順帶一提,筆者將原始程式放在 http://www.microsoft.com/mind/22 ,這是筆者在98年9月所碰到的問題。)該控制項使用了MsXml元件,嚴格遵守1.0版的標準。結果,它無法處理筆者自己撰寫的XML scriptlet。不用說,這些有問題的scriptlet全部在執行時期良好運作。在這些個案中,script標籤全部包含了運算字元大於(>)或小於(<)。除非你在它們前面放上空白字元,否則解析器會混淆,並利用它們來關閉標籤或開啟標籤,產生無法預料的結果。

要加強執行時期的檢查,並避免鬆散的HTML-based語法規則,你可以在XML scriptlet的起始部分加入類似下面這行程式:

<?XML version="1.0"?>
version屬性的內容是程式被宣告將遵守的XML標準的版本號碼。如果發生錯誤,XML scrptlet物件將不會建立。幾乎所有前面介紹過的程式片段都與1.0的標準不相容。筆者謹慎地完成這個工作來指出哪裡可能發生錯誤。程式不相容的原因是因為它們違反了這兩個規則之一:

&reg;所有標籤與屬性的名字都必須是小寫字元。

&reg;23所有屬性的內容都必須利用引號包圍,不管是單引號或雙引號皆可。

為了遵守1.0標準,必須要求在script程式中於「<」與「>」之前加入空白字元,即使是這些符號是用於註解程式。要讓XML與1.0標準相容,又想免於使用空白字元的麻煩,那麼就將整個script程式放置在<![CDATA[...]]>區段中。中括號將函式的程式包圍。下面就是一個簡單的範例:

<script language="VBScript">
<![CDATA[
Function method()
' place here the script code
End Function
]]>
這個解決方案與所使用的script語言無關,所以你也可以利用JScript的script來撰寫。

結論


雖然DHTML scriptlet較早出現,但XML scriptlet的功能及普及度卻來得比較大。然而,其實兩者對開發人員而言都非常有用,各自在應用程式中有其專屬的最佳特性。所以,當你的網頁需要一個獨立且包含使用者界面的物件時,那麼使用DHTML scriuptlet可能比較合適(當然你也可以考慮使用DHTML behavior)。然而,如果你需要的是將具有親切且容易使用的程式設計界面物件使用在任何地方,像是ASP網頁、HTML網頁、桌上型應用程式與WHS等,那麼只有一個答案:XML scriptlet。
mic64 目前離線  
送花文章: 0, 收花文章: 21 篇, 收花: 61 次