Script宿主、Script引擎、Script(腳本)之間的關系
要想實現基於COM組件的腳本支持功能,我們需要正確理解Script各方以及相互之間的關系。有關腳本的概念有:Script Host(Script宿主)、Script Engine(Script引擎)、Script(腳本) 。
什麼是Script宿主呢?聽起來象生物學術語。類似生物學的概念,可以簡單認為是我們所編寫的腳本要控制的功能對象,是我們編寫的應用程序,想提供給最終用戶的功能組件。舉例說,Word是微軟提供給大家的文字處理系統,它采用了基於COM的軟件結構,如果我們為Word編寫一些腳本(就是平常所說的“宏”),那麼,腳本所依附的對象 Word就是Script宿主了。腳本功能的最終執行者就是Script宿主。我們編寫的任何自主應用程序都可以看作宿主,都可以嵌入腳本解釋能力。當然,宿主應當是也最好是基於COM編程的。另一方面,腳本就是對宿主進行服務請求或進行控制的代碼。
Script引擎就是Script宿主和Script之間的“橋梁”。腳本引擎獲取腳本,並按照語法進行解釋,並控制宿主程序提供的對象的屬性,調用相關方法,實現腳本要求的功能。向腳本提供可利用的對象並解釋腳本以實現二次開發是引擎的主要功能。
三者之間的關系可以用如下的圖形來表示。
--------------------------------------------------------------------------------
向腳本控件提供對象
--------------------------------------------------------------------------------
控制宿主提供的對象
從輸入部件獲取要解釋執行的腳本
Script引擎對象的屬性、方法、事件
Script引擎是作為一個ActiveX控件提供給用戶的,在利用它之前,我們來看一看此控件的屬性和方法。
屬性:
AllowUI:可讀寫,布爾值,檢測是否允許運行用戶的接口元素。如果為False,則諸如消息框之類的界面元素不可見。
CodeObject:返回宿主被調用的特定的公用成員對象。只讀。
Modules:只讀。返回宿主提供給腳本的組件庫模塊。COM組件通常都是以對象收集的形式向用戶提供可以留給用戶二次開發的對象集合,每一個收集即一個Modules(模塊)。
Language:設置或獲取腳本引擎解釋的語言,例如:VBScript、JScript。
Name:返回模塊、過程、或者對象的名字,只讀屬性。
Procedures:返回模塊中定義的過程,只讀。
SitehWnd:窗口句柄,如果本控件以ActiveX控件創建,則此屬性為控件的容器;如果是以自動化對象創建,則為0,即桌面。此屬性可讀寫。
State:設置或返回控件的狀態,如果為0,控件只執行語句但不轉發事件,為1則為加入的本控件接受的對象轉發事件。
Timeout:設置或返回控件的相應腳本的超時值。當超時值到達時,將引發Timeout事件。也可設為-1,表示無超時設定。
UseSafeSubset:設置或返回宿主程序是否關心安全。宿主程序的安全級別可以從此屬性設置。
Error:錯誤對象,發生錯誤時,此屬性返回一個錯誤對象。
方法:
AddCode :往一個模塊加入一些代碼。格式為:AddCode code, 可以調用多次。
AddObject:向一個模塊加入一個對象,格式:ScriptControl.AddObject(name, object[, addMembers]),name為欲加入的對象名字,Object為實際的對象,addMembers為可選指示此對象是否為全局對象,False為局部對象。只有往本對象中加入對象後才能在腳本中使用這些對象。
Eval:求值表達式。格式為object.Eval(expression) 。
ExecuteStatement:解釋並執行腳本語句。格式:object.ExecuteStatement statement。
Reset:丟棄所有的對象和代碼。State屬性將為0。
Run:運行一個指定的過程。格式:object.Run(procedureName, parameters()),procedureName為要運行的過程名,parameters()為
事件
僅有兩個事件:error 和TimeOut。前者可以用於錯誤捕獲,後者在腳本得不到響應時發生。
VB開發實例
假設我們要在VB中開發一個編輯軟件,此系統顯然就是前文提到的腳本技術中的宿主,為了支持二次開發將系統設計為基於COM,並且向用戶提供兩個對象“Word”及“MyBox”。
實際上為了簡化問題,達到演示說明的目的,此例子並未自行設計復雜的代碼,向用戶提供的對象實際都是“現成”的棗“WORD”就是您系統中安裝的Office中的Word,只不過被我“轉手”以“我提供的對象”形象出現,在Office VBA中Word所有的方法屬性都可以在本系統的腳本功能中提供給用戶;“MyBox”實際上是設計時添加的一個TextBox控件,但最終是以我的文本框提供給使用者。界面很簡單(樸素?投機取巧?),盡量不轉移大家的注意力,以了解本文所述的腳本技術實現。代碼及注釋如下:
VERSION 5.00
‘需要使用一個自動化服務器和一個ActiveX控件支持本例子。
Object = "{0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}#1.0#0"; "MSSCRIPT.OCX"
Begin VB.Form Form1
Caption = "具有腳本支持功能的演示系統"
ClIEntHeight = 4335
ClIEntLeft = 60
ClIEntTop = 345
ClIEntWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 4335
ScaleWidth = 4680
StartUpPosition = 3 ''Windows Default
Begin VB.TextBox Text2
Height = 1095
Left = 120
MultiLine = -1 ''True
TabIndex = 2
Text = "vbscript.frx":0000
‘用戶可以通過腳本代碼窗輸入控制此對象的屬性的代碼(我的對象名字為MyBox),也可以通過Word對象來啟動並控制您系統中的Office Word
ToolTipText = “在腳本代碼框中輸入代碼以控制本對象的屬性 ”
Top = 3120
Width = 2415
End
Begin VB.TextBox Text1
Height = 2295
Left = 120
MultiLine = -1 ''True
ScrollBars = 3 ''Both
TabIndex = 1
Text = "‘在此輸入腳本代碼"
ToolTipText = " 你可以在代碼中控制兩個本系統提供的對象:Word和MyBox。"
Top = 480
Width = 4335
End
Begin VB.CommandButton Command1
Caption = "執行腳本代碼"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 0
Weight = 400
Underline = 0 ''False
Italic = 0 ''False
Strikethrough = 0 ''False
EndProperty
Height = 735
Left = 2760
TabIndex = 0
Top = 3480
Width = 1815
End
‘腳本對象的缺省屬性
Begin MSScriptControlCtl.ScriptControl ScriptControl1
Left = 0
Top = 2160
_ExtentX = 1005
_ExtentY = 1005
AllowUI = -1 ''True
End
Begin VB.Label Label1
Caption = "請在此輸入您的VB代碼"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 0
Weight = 400
Underline = 0 ''False
Italic = 0 ''False
Strikethrough = 0 ''False
EndProperty
Height = 255
Left = 120
TabIndex = 3
Top = 120
Width = 3255
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Sub Command1_Click()‘當點擊Command1 時
ScriptControl1.ExecuteStatement Text1.Text‘解釋並執行腳本
End Sub
Private Sub Form_Load() ‘窗體載入時
Dim ob As Object ‘定義一個對象變量
Set ob = CreateObject("Word.Application")‘創建一個自動化對象,引用編程ID
ScriptControl1.State = Connected‘設置腳本控件的狀態
ScriptControl1.AddObject "WORD", ob ‘向腳本對象加入一個可接收的對象“Word”
ScriptControl1.AddObject "MyBox", Text2 ‘加入一個本窗體的VB基本控件TextBox
End Sub
實例的運行要求:VB6.0、Pwin98,並且原則上要求您的系統中安裝Word97,但如果您可以將Form_Load()中的CreateObject("Word.Application")語句修改,把“Word.Application”(Word97的在注冊表中的ProgID)替換成任何您系統中現有的任何自動化對象的ProgID。在啟動本例子後你可以在腳本輸入框中輸入如下代碼以觀察效果,也可以在了解腳本提供的對象的屬性和方法基礎上寫入您自己的任何代碼:
Word.visible =True ‘使Word對象顯現,跟通過常規方法啟動它一樣使用它。
MyBox.Text =“這是在腳本中設置的內容”
補充幾點
關於宿主提供的對象。
可以在編寫宿主時添加任何自定義的對象,在本例這些對象可以是VB編寫的對象、VB提供的控件(包括ActiveX控件)、系統中存在的自動化對象(甚至您用其它諸如Delphi等編寫的控件、COM對象),但對於自定義對象必須用AddObject方法加入到腳本控件Modules。
對運行時對象的控制
在使用Object.xxx形式引用對象的方法和屬性時必須要確認所輸入代碼的有效性。所謂“有效性”是指在腳本控件解釋這些代碼時所引用的屬性、方法等必須可用或有效(有些屬性只讀或只寫,有寫方法在某些狀態下不能調用),不能出現拼寫錯誤。本例子未進行錯誤捕獲,感興趣大家可以自行設計。
C++中的腳本引擎利用
除了在VB中可以使用ScriptControl外還可以在C++中使用它。Visual Studio97中使用腳本功能必須實現一些特殊的接口,比較繁瑣,利用此控件可以省下腳本支持接口方面的周折。我們開發的很多自主軟件都沒有利用腳本支持功能,導致軟件使用和二次開發不便,例如WPS97就沒有類似Word97的宏功能,應該說是我們國產軟件同世界軟件之間的一個差距(因手頭沒有 WPS2000,所以無法對其進行評論)。一般現在開發軟件利用C++可以方便的實現COM,可以利用腳本控件輕松實現腳本支持,為自己的軟件增色,何樂而不為呢?