VBScript 程式設計
VBScript,是 Visual Basic Scripting Edition 的簡稱,是微軟提供的類似於 Visual Basic 和 Visual Basic for Applications 的指令碼語言。 它可以透過 Windows Script Host (WSH) 作為 Windows 指令碼語言使用。 此外,它可以作為網頁中的客戶端指令碼語言代替 JavaScript 使用,但此類頁面只能在 Internet Explorer 中使用。 此外,它可以作為 Active Server Pages (ASP) 的一部分用於伺服器端網頁尾本,以及在其他環境中使用。 本書重點介紹透過 WSH 使用該語言。
要與 WSH 一起使用的指令碼通常是帶有 .vbs 副檔名的純文字檔案。 預設情況下,Windows 將該副檔名與該語言的直譯器關聯,因此,在 Windows 批處理命令列中輸入指令碼名稱會導致指令碼執行,儘管不會等待指令碼完成。 此外,指令碼可以從桌面或 Windows 檔案資源管理器執行,通常透過雙擊執行。
VBScript 可以訪問透過 Microsoft COM 介面提供的物件,包括 Microsoft Office 的物件。 因此,Microsoft Office 不僅可以從嵌入在諸如電子表格之類的 Office 檔案中的 Visual Basic for Applications (VBA) 中進行指令碼化,還可以從 VBScript 指令碼中進行指令碼化,以語法相似但略有不同的方式進行。
有兩個命令可用於讓 WSH 執行指令碼:wscript 和 cscript。 wscript 用於透過簡單的彈出視窗進行互動,而 cscript 用於透過文字控制檯進行命令列互動。 預設情況下,.vbs 副檔名與 wscript 相關聯。
VBScript 在關鍵字和識別符號方面大多不區分大小寫。 因此,“End If” 等效於“end if”,而 “FSO.CreateTextFile( ...)” 等效於 “fso.createtextfile( ...”。
與 VBA 不同,變數不能被定義為僅限於特定資料型別的值,例如 String。 相反,它們都是 Variant 資料型別。
但是,每個變數仍然有一個底層資料型別,這取決於你分配給該變數的值。 你可以使用 TypeName 函式(返回字串)和 VarType 函式(返回整數)來了解變數內容的當前底層資料型別。
連結
- VBScript 資料型別,Microsoft Docs
- TypeName,ss64.com
- VarType 函式,docs.microsoft.com
- VBScript 內建函式,ss64.com
各種資料型別字面量的示例
a = 3 'Integer: signed 16-bit integer
b = 2147483647 'Long: signed 32-bit integer
c = 3.5 'Double floating-point number
d = 1.7E-10 'Double floating-point number
e = &H7FFFFFFF 'Long; hexadecimal literal
f = &HFFFFFFFF 'Integer, whyever; value -1; arguably a bug or a trap
g = CLng("&HFFFFFFFF") 'Long -1
h = &H8000& 'Long via the final &; 32768
h = &HFFFFFFFF& 'Integer; the final & did not help make this Long; value -1; arguably a bug or a trap
i = &O666 'Integer; octal literal
i = &O177777 'Integer; -1
i = &O177777& 'Long via final &; 65535
i = &O37777777777 'Integer; -1; a bug or a trap
i = &O37777777777& 'Integer; -1; a bug or a trap
i = &666 'Integer; octal literal without O after &
j = "Hello" 'String
k = True 'Boolean; -1 when converted to an integer
l = #1-Jan-2020# 'Date
m = #Jan-2-2020# 'Date, month first
n = #1-2-2020# 'Date, month first: Jan 2, 2020
n = #2020-02-01# 'Date, ISO format
o = #Jan-2-2020 2:20:13 PM# 'Date, with time
p = #Jan-2-2020 14:20:13# 'Date, with time
不是字面量但具有相同用途的示例
a = CCur(922337203685477) + CCur(5807) / 10000 'Currency: 64-bit fixed-point real number with 4 decimal places
b = CCur(-922337203685477) - CCur(5808) / 10000 'Currency
c = CByte(255) 'Byte; unsigned 8-bit integer
'c = CByte(-1) 'Error
d = CLng(5) 'Long
e = CSng(1.5) 'Single precision floating point
f = Array(1, 2.5, "s", Array(3, 4)) 'Array
VBScript 透過 Scripting.Dictionary 物件支援字典,也稱為關聯陣列。 鍵可以是除陣列之外的任何型別; 因此,字串、整數、浮點數、日期等都是支援的。
示例
Set Dict = CreateObject("Scripting.Dictionary")
Dict.Add "Key", "Value"
Value = Dict.Item("Key")
If Dict.Exists("Key") Then
WScript.Echo "Key exists"
End If
Dict.Remove "Key"
Dict.Add "DE", "Germany"
Dict.Add "USA", "United States"
Dict.Item("USA") = "The United States" 'Member rewrite
Keys = Dict.Keys 'An array, not a collection
For Idx = 0 To Dict.Count - 1 'For each key
WScript.Echo "Key " & Keys(Idx)
WScript.Echo "Value " & Dict.Item(Keys(Idx))
Next
連結
- Dictionary 物件,docs.microsoft.com
對於使用者互動的輸入和輸出,Windows 指令碼宿主中的 VBScript 提供了一個簡單的彈出訊息框和一個簡單的彈出輸入框,它們適用於透過 wscript(預設值)和 cscript 兩種方式進行指令碼呼叫。 文字控制檯輸入和輸出在透過 wscript 執行的指令碼中不受支援; 需要透過 cscript 執行。
透過 WScript 物件進行輸入的示例,主要是透過文字控制檯
WScript.Echo "Hello" 'Works both via wscript (makes a popup window)
'and cscript (outputs to a console).
WScript.Echo "Multiple items and types:", 4, 3.5, #1-Jan-2020#
' ^ The items separated by commas are output space-separated.
If InStr(1, WScript.FullName, "cscript", vbTextCompare) Then
' ^ Tests whether we are running via cscript, not wscript.
WScript.StdOut.Write "Enter an integer:" 'Only works via cscript, not wscript.
' ^ Outputs to text console. Writes no newline.
str = WScript.StdIn.ReadLine() 'User input from console
WScript.StdOut.WriteLine "Entered " & str 'Writes a newline.
WScript.StdErr.WriteLine "Test error message" 'Standard error stream is available.
Else
WScript.Echo "Not running via cscript. Some examples are skipped."
End If
透過彈出視窗進行輸入和輸出的示例,適用於 wscript 和 cscript
MsgBox "Hello"
MsgBox "Hello 2", 0, "Window Title"
str = InputBox("Enter an integer")
int1 = CInt(str) 'Converts string to int
MsgBox int1 + 1
有關從文字檔案讀取和寫入文字檔案的資訊,請參閱 #檔案操作。
獲取命令列引數的示例
i1 = WScript.Arguments.Item(0)
i2 = WScript.Arguments.Item(1)
WScript.Echo CInt(i1) + CInt(i2)
獲取環境變數的示例
Set Shell = CreateObject("WScript.Shell")
HomeDrive = Shell.ExpandEnvironmentStrings("%HOMEDRIVE%")
HomePath = Shell.ExpandEnvironmentStrings("%HOMEPATH%")
WScript.Echo HomeDrive & HomePath
連結
- .Echo,ss64.com
- StdOut.Write,ss64.com
- .StdOut.ReadLine ,ss64.com
- MsgBox,ss64.com
- InputBox,ss64.com
- 如何:有用的 WScript 屬性列表,ss64.com
- 如何:VBScript 命令列引數,ss64.com
- .ExpandEnvironmentStrings,ss64.com
與 VBA 不同,檔案操作不是語言內建核心的一部分,而是可以從 FileSystemObject 訪問。
從文字檔案讀取
FileName = "MyFile.txt"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set File = FSO.OpenTextFile(FileName)
While Not File.AtEndOfStream
Line = file.Readline() 'Line has no newline.
'Process Line
WScript.StdOut.WriteLine Line 'Works only via cscript
Wend
File.Close
寫入文字檔案
FileName = "MyFile.txt"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set File = FSO.CreateTextFile(FileName, True)
File.Write "Hello, there." & vbCrLf
File.Close
MsgBox "File " & FileName & " written."
獲取當前目錄
Set FSO = CreateObject("Scripting.FileSystemObject")
CurrentDirectory = FSO.GetAbsolutePathName(".")
MsgBox CurrentDirectory
使用 ADODB.Stream 從二進位制檔案讀取位元組
Bytes = ReadBytes("MyFile.bin")
For Each Byte_ in Bytes
WScript.Echo Byte_
Next
Function ReadBytes(FileName)
'Read bytes into variant array of bytes
Dim OutBytes()
'SetLocale "ja" 'Uncomment to test locale independence
Set Stream = CreateObject("ADODB.Stream")
Stream.Open
Stream.Type = 1 'Binary mode
Stream.LoadFromFile FileName
ReDim OutBytes(Stream.Size - 1)
'Stream.Position = 10 'Skip first 10 bytes if you wish
J = 0
While Not Stream.EOS
Bytes = Stream.Read(1000) 'Read a block of up to 1000 bytes
'Bytes = Stream.Read() 'Or read them all: we would not need the while loop
'VarType(Bytes) = 8209 'Byte array, not variant array
For I = 0 To UBound(Bytes)
Byte_ = AscB(MidB(Bytes, I + 1, 1)) 'vartype(Byte_) = 17, which is Byte
OutBytes(J) = Byte_
J = J + 1
Next
Wend
Stream.Close
ReadBytes = OutBytes
End Function
使用 ADODB.Stream 將位元組寫入二進位制檔案
Set Stream = WScript.CreateObject("ADODB.Stream")
Stream.Type = 2 'Text mode
Stream.Charset = "iso-8859-1"
Stream.Open
'Write test bytes from 0 to 255
For I = 0 to 255
Stream.WriteText ChrW(I)
Next
Stream.SaveToFile "MyFile.bin", 2 '2=Overwrite file
Stream.Close
上面,訣竅是使用 iso-8859-1 以及 ChrW。 一個需要注意的是,iso-8859-1 沒有定義控制程式碼,因此它們從 Unicode 到 iso-8859-1 的對映在形式上是未定義的,但在 ADODB.Stream 中選擇了一個實現定義的對映,因此它無論如何都能正常工作。 以上不能透過將 Chr(num) 寫入文字檔案來使用 FileSystemObject 可靠地實現,因為這隻能在某些區域設定中工作,而不能在其他區域設定中工作。
連結
- FileSystemObject,ss64.com
- FileSystemObject,Microsoft Docs
- Stream 物件 (ADO),docs.microsoft.com
- 二進位制檔案和檔案系統物件不相容,blogs.msdn.microsoft.com
- ISO-8859-1 是 Unicode 字元集嗎?,stackoverflow.com
- ISO/IEC_8859-1,wikipedia.rog
位元組陣列與位元組的變體陣列形成對比。 在 VBScript 中,所有宣告的陣列都是變體陣列,並且它沒有直接和簡單的方法來建立位元組陣列。 儘管如此,位元組陣列仍然可以建立,即使是以更冗長的方式,並且依賴於 ADODB.Stream。
填充位元組陣列,然後讀取迭代它
'Populate byte array
Set Stream = CreateObject("ADODB.Stream")
Stream.Type = 2 'Text mode
Stream.Charset = "iso-8859-1"
Stream.Open
'Write test bytes from 0 to 255
For I = 0 to 255
Stream.WriteText ChrW(I)
Next
Stream.Position = 0
Set Stream2 = CreateObject("ADODB.Stream")
Stream2.Type = 1 'Binary mode
Stream2.Open
Stream.CopyTo Stream2
Stream2.Position = 0
ByteArray = Stream2.Read() 'VarType(ByteArray) = 8209 'Byte array, not variant array
Stream2.Close
Stream.Close
'Read-iterate byte array
For i = 0 To UBound(ByteArray)
Byte_ = AscB(MidB(ByteArray, i+1, 1))
WScript.Echo Byte_
Next
上面,填充位元組陣列使用的是將 Unicode 程式碼點寫入 0-255 範圍內的 iso-8859-1 編碼的文字流,將文字流複製到二進位制流,然後從二進位制流讀取位元組。 讀取迭代位元組陣列很簡短,使用的是組合 MidB 和 AscB 的技巧,而不是陣列索引訪問。
算術運算子包括 +、-、*、/(真除法)、\(整數除法)、^(指數)和 mod(模運算)。 整數除法向零截斷,就像在 C 語言中一樣:-3 \ 2 = -1。 整數除法在執行除法之前將運算元轉換為整數型別(對其進行舍入):3.6 \ 2 = 2(Long)。 模運算是在向零截斷的整數除法後的餘數,因此,-3 mod 2 = -1,就像 C 的 -3 % 2,而不是像 Python 的 -3 % 2 == 1。
比較運算子包括 =、<>、<、>、<=、>= 和 Is。
位運算子包括 And、Or、Xor、Not、Imp 和 Eqv。這些運算子在整數型別(Byte、Integer、Long)上作為位運算子操作。當對負整數進行操作時,它們的行為符合有符號整數的二進位制補碼內部表示。沒有位移和位旋轉運算子,但它們可以被模擬。
布林邏輯運算子與位運算子相同。當對布林值(包括布林表示式)進行操作時,位運算子充當布林邏輯運算子,沒有短路計算,True 為 -1。因此,True and 14 產生 14,因為 -1 作為 Integer(16 位)為 0xFFFF。
數學函式包括 Abs、Atn、Cos、Exp、Fix、Int、Log、Randomize、Rnd、Round、Sgn、Sin、Sqr 和 Tan。
字串連線運算子為 &(推薦)和 +(不推薦)。
在另一本華夏公益教科書中,參見 Active Server Pages/附錄 A:語言參考。
連結
- 運算子 (VBScript),docs.microsoft.com
- VBScript 功能,docs.microsoft.com
- 如何操作:VB 指令碼運算子,ss64.com
- VBScript 內建函式,ss64.com
Excel 可以使用 VBScript 透過訪問 Excel.Application 物件進行指令碼化。與 VBA 不同,VBScript 不支援對方法使用命名引數傳遞,只支援位置引數傳遞。此外,從 VBA 中看起來是全域性的函式在 Excel 中需要作為 Excel 物件的方法呼叫。此外,Excel 的特定常量,如 xlAnd,不可用;您需要自己定義常量或使用數字代替。
一個例子
Set FSO = CreateObject("Scripting.FileSystemObject")
CurrentDirectory = FSO.GetAbsolutePathName(".")
Set Excel = CreateObject("Excel.Application")
Set Workbook = Excel.Workbooks.Open(CurrentDirectory & "\" & "MyFile.xlsx")
Workbook.Sheets(1).Cells(1, 1).Value = "Hey"
Workbook.Save
Workbook.Close
連結
- Microsoft Excel 常量,Microsoft Docs
有多個內建常量,以 vb 開頭。例如,vbOKCancel 用於與 MsgBox 結合使用。
應用程式特定的常量(例如 Excel 的 xlAnd)不可用。
連結
- VBScript 內建常量,ss64.com
- Microsoft Excel 常量,Microsoft Docs
- Microsoft Outlook 常量,Microsoft Docs
- Word 列舉常量,Microsoft Docs
VBScript 不支援 VBA 的 MSForms.DataObject 來訪問剪貼簿。
有一些變通方法
- 要寫入剪貼簿,您可以執行 Windows 7 中提供的 clip.exe。
- 要從剪貼簿讀取,您可以透過 COM 訪問 Internet Explorer,並讓它從剪貼簿讀取。
連結
- VBScript,將文字複製到剪貼簿,以便貼上到任何欄位,stackoverflow.com
您可以使用 WScript.Shell 的 Run 方法執行外部程序
Set Shell = WScript.CreateObject ("WScript.Shell")
Shell.Run "tasklist /v", 0, True
您也可以使用 WScript.Shell 的 Exec 方法。
Set MyShell = CreateObject("WScript.Shell")
Set ExecObject = MyShell.Exec("tasklist /v")
' AllText = ExecObject.StdOut.ReadAll
Do While Not ExecObject.StdOut.AtEndOfStream
Line = ExecObject.StdOut.ReadLine()
If InStr(Line, "AcroRd32.exe") > 0 Then
'Do something
End If
Loop
關鍵字:外部命令,執行程式。
在另一本華夏公益教科書中:Excel VBA#命令輸出。
連結
- 執行程式 在 Microsoft Windows 2000 指令碼指南中,TechNet 存檔,Microsoft Docs
- .Run,ss64.com
- wscript.Shell + Shell.Application 物件,ss64.com
您可以使用 RexExp 物件使用正則表示式
Set RegExp = New RegExp
RegExp.Pattern = "[0-9][0-9]*"
If RegExp.Test("354647") Then
MsgBox "Test passed."
End If
或者,您可以透過 Set RegExp = CreateObject("VBScript.RegExp") 建立正則表示式物件,但在 VBScript 中,這是不必要的。
連結
- Microsoft 使用正則表示式增強 VBScript,docs.microsoft.com
- VBScript 的正則表示式支援,regular-expressions.info
在支援 Unicode 的平臺上,VBScript 與 WSH 結合使用,對 16 位 Unicode 有以下支援
- 指令碼原始碼可以儲存在 UTF-16 LE(小端)中,然後,字串文字可以是 Unicode。變數名和過程名不能是 Unicode。UTF-16 BE(大端)和 UTF-8 不受支援。具有 BOM 的 UTF-8 指令碼將無法執行。沒有 BOM 的 UTF-8 指令碼可能執行,但字串文字中超過 127 的字元在透過 MsgBox 和其他介面輸出時將被亂碼。
- UCase 和 LCase 支援 Unicode,MsgBox 也支援。
- 可以透過將程式碼點編號傳遞給 ChrW 函式來輸入 Unicode 字元。ChrW(127) = Chr(127),而 ChrW(128) <> Chr(128)。
- 可以透過 AscW 獲取字元的 Unicode 程式碼點編號。
- FileSystemObject 方法 OpenTextFile 和 CreateTextFile 支援讀取和寫入 UTF-16 LE Unicode,方法是在可選引數中指示這樣做。
- ADODB.Stream 物件支援將 Unicode 寫入檔案,並透過將 Stream.Charset 設定為 "utf-8" 從 UTF-8 檔案中讀取,以及以其他編碼(如 "ascii" 或 "iso-8859-1")讀取。您可以透過 cmd.exe 命令列從 "reg query HKEY_CLASSES_ROOT\MIME\Database\Charset" 獲取編碼列表,或透過 PowerShell 從 "dir Registry::HKEY_CLASSES_ROOT\MIME\Database\Charset" 獲取編碼列表。
連結
- Stream 物件 (ADO),docs.microsoft.com
- 將 UTF-8 檔案轉換為 Vbscript 中的 UTF-16 BE 檔案,stackoverflow.com
- ActiveX 資料物件,wikipedia.org
- FileSystemObject,ss64.com
- FileSystemObject,Microsoft Docs
VBScript 具有預期的保留關鍵字,例如 Dim 或 While;這些關鍵字不能用作變數名。但是,它還有一些保留關鍵字來自 VBA,VBScript 語法沒有使用,例如 Byte 和 Long。
VBScript 版本包括 5.1(Win 2000)、5.6(XP)、5.7(Vista)和 5.8(Win 7、Win 10)。
連結的 Microsoft 文件中每個版本新增的功能表顯示 2000 年以後沒有新增任何功能。
指令碼主機版本應與指令碼引擎版本區分開來。
要了解引擎版本和 Windows 指令碼主機版本
VBScriptVersion = ScriptEngineMajorVersion & "." & ScriptEngineMinorVersion
WSHVersion = WScript.Version
WSHBuildVersion = WScript.BuildVersion
執行沒有 //nologo 開關的 cscript 將輸出指令碼主機版本。
連結
- VBScript 版本資訊,Microsoft Docs
- Windows 指令碼主機#版本歷史,wikipedia.org
VBScript 中缺少而 VBA 中存在的功能
- 對函式和方法使用命名引數傳遞
- 應用程式特定的命名常量(例如 Excel 的 xlAnd)不可用;您必須自己設定它們或傳遞數字代替
- 內建檔案 I/O;VBScript 可以使用 FileSystemObject
- 透過 new Collection 建立自定義集合
- 使用特定資料型別對變數進行維度化
- 等等。
連結
- VBScript 中沒有的 Visual Basic for Applications 功能,Microsoft Docs
- VBScript 是否允許在函式呼叫中使用命名引數?,stackoverflow.com
限制
- #與 VBA 的比較中描述的限制適用。特別是,無法建立自定義集合,因此不支援許多程式語言中已知的可輕鬆擴充套件列表;解決方法包括根據需要重新調整動態陣列的大小或將索引儲存為字典中的數字鍵。
- 一般來說,與基於 .NET 的 PowerShell 或 Python 相比,作為庫提供的功能很少;相反,上面提到的兩種指令碼技術擁有非常多的庫來支援各種任務。
- 沒有互動式 shell 來逐個執行 VBS 命令,這與基於 .NET 的 PowerShell 或 Python 不同。
- 對於透過 wscript 執行的指令碼,沒有從控制檯讀取和寫入,只有透過 cscript 執行的指令碼。
- 對陣列操作的支援有限,例如沒有排序函式。使用者只能編寫自己的排序函式。
- 沒有直接的方法將其他 .vbs 指令碼作為庫包含進來;間接方法是透過 WSF XML 檔案。
- 沒有按位左移和右移運算子,但可以輕鬆實現。
- 無法從 .vbs 指令碼中進行一般的 GUI 程式設計;另一種方法是在 HTML 中將 VBS 嵌入為 HTML 應用程式 (HTA)。無需 HTA,可以直接支援簡單的訊息框和輸入框。
- 沒有任意精度的整數運算。
- 沒有集合型別(數學集合)。
- 還有更多。
Windows 指令碼宿主中的 VBScript 曾是 Windows 管理員的熱門選擇。截至 2022 年,它的使用早已減少,並被 PowerShell 遠遠超過。VBScript 引擎自 2001 年以來就沒有進行過重大更新,微軟已將 PowerShell 定位為 Windows 管理的首選指令碼技術。經典 ASP 中的 VBScript 早已被 ASP.NET 中的 VB.NET 和 C# 超越。與 VBScript 不同,VBA 仍在廣泛使用。
連結
- VBScript、PowerShell、Visual Basic for Applications、COBOL,trends.google.com
- VBScript、PowerShell、VBA、COBOL 在 Google Ngram Viewer 中,google.com
- vbscript、vba、powershell 在 Stack Overflow 趨勢中,stackoverflow.com
- TIOBE 指數,tiobe.com
在 WSH 中,經常將 COM 元件與 VBScript 配合使用。
- WScript.Shell
- WScript.Network
- Scripting.FileSystemObject
- Scripting.Dictionary
- Shell.Application
- Excel.Application
- Word.Application
- Outlook.Application
- InternetExplorer.Application
連結
- Windows 指令碼宿主物件模型,Microsoft Docs
- Active Server Pages
- Active Server Pages/附錄 A:語言參考 -- 單頁概述
- Visual Basic
- Excel VBA
- Visual Basic for Applications
- VBScript 語言參考,Microsoft Docs
- VBScript 語言參考,標識為 vs.85,docs.microsoft.com
- VBScript 功能,docs.microsoft.com -- 按類別分組的關鍵字索引
- WSH 簡介,TechNet 檔案,Microsoft Docs
- 程式設計中的奇妙冒險,一個部落格,microsoft.com
- VBScript 命令,ss64.com
- VBScript 操作指南和示例,ss64.com
- VBScript,wikipedia.org
- Windows 指令碼宿主,wikipedia.org
- 類別:VBScript,rosettacode.org
- JavaScript 和 VBScript 程式碼比較,harding.edu -- 單頁備忘單