MS_VBS - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki
- 戻る(シェル、スクリプティング、Visual Basic)
- BAT
- VBScript
- PowerShell
- WSH
トピック情報を纏めています。
- 言語構文やプログラミングの解説は、ここでは割愛します。
- 下記のガイドや、「vbs | vbscript やりたいこと」でググるなどしてください。
豊富なサンプル、Q&A が、ネット上に多数転がっています。 - ネット上に転がっていたスクリプトを引用する際は、権利関係に注意ください。
(特に、まるまる引用するような場合)
補足(最新化:非推奨化が進行中): VBScript は
2023 年 10 月に Microsoft が非推奨(deprecated)を公表した。
段階 状況 第 1 段階 Windows 11 24H2 以降、**オンデマンド機能(FoD)**として提供(既定で有効) 第 2 段階 既定で無効に 第 3 段階 完全に削除 新規に VBScript を書く理由はもう無い。
既存資産は PowerShell への移行を計画すること
(スクリプティングに移行の勘所を記載)。本ページの内容は、既存資産を読み解く/保守するための
参照情報として有用である。
-
VBScript は、Excel VBA に似ています。
- Excel のモジュールシートに記述する感じで記述できます。
- ただ、構文や機能に、できることの違いが少しあります。
-
リファレンスの「VBScript ユーザーズ ガイド」から、
- 「VBScript の機能で VBA に含まれていない機能」
- 「VBA の機能で VBScript に含まれていない機能」
を参照してください。
VBScript ファイルは、vbs と wsf の 2 種類あり、
どちらも WSH のスクリプトを記述します。
| 拡張子 | 内容 |
|---|---|
.vbs |
VBScript のみを記述。 |
.wsf |
XML ファイルで、VBScript のほか、JScript / 参照する TypeLib / 参照する(取り込む)script ファイルも記述できる。 |
以下、個別に。
VBScript で値を代入するときは、let 文を使います。
ただし、代入するものが object の場合は、set 文を使います。
let str1 = "abcde"
str2 = "ABCDE"
set fso = CreateObject("Scripting.FileSystemObject")普通は、let は省略して、上の str2 の代入の様に書きます。
関数の戻り値の場合も同じで、戻り値を返す関数では、関数名へ set を使って代入します。
filename = "c:\temp\tempfile.txt"
set fso = CreateObject("Scripting.FileSystemObject")
set tmp1 = makeTempFile(filename)
tmp1.writeline "てすと"
tmp1.close
set tmp1 = nothing
function makeTempFile(fn)
dim f
set f = fso.OpenTextFile(fn, 2, True) ' 2=書き込み, True=作成
set makeTempFile = f
end function上の例の様に、sub ... end sub は、値を返さない関数を定義します。
値を返す場合は、function を使います。
function amari(a, b)
amari = ( a mod b )
end function
print amari( 20, 3 )- 関数名と同じ変数へ代入します。
- 関数の戻り値の型は指定できません。
(vb や vba にあるfunction funcname(arg1, arg2) as typeのas typeは
記述できません)
a mod b は、a を b で割った剰余を求める演算子です。
- 値を必要とする場所(代入の右辺、別の関数の引数、式の途中)などに、
関数名(引数,..)の様に記述して呼び出します。 - また、値を必要としない場所では、
関数名 引数,..の様に( )をつけずに記述します。 - 値を必要としない場所に
( )をつけて記述する場合は、
call 関数名(引数,..)の様にして戻り値を無視するようにします。
call 関数名(引数,..) / 関数名(引数,..) / 関数名 引数,.. どの形式でも使用できます。
補足(引数の括弧の罠): VBScript で最も分かりにくい仕様がここである。
引数が 1 つのとき、Foo (x)と書くと
(x)が「式の評価」と解釈され、値渡しになる。Sub Increment(ByRef n) n = n + 1 End Sub Dim v : v = 1 Increment v ' → v は 2 になる Increment (v) ' → v は 1 のまま(値渡しになる)
ByRefのつもりが効かない、という不具合の典型的な原因である。
- VBScript では、
dim文で変数を定義します。 - スコープ
- 関数の外で定義すると、グローバル変数になります。
-
classの中で定義することで、class のローカル変数にすることもできます。 -
subまたはfunctionの中で定義した変数は、その関数の中がスコープになります。
- VBScript は、
dim文を省略することもできますが、
変数のはじめに現れた場所に依存して、スコープが関数内またはグローバルに決定されます。 - 変数名の誤字によるバグを回避したり、変数のスコープを管理するためにも、
VBScript ファイルの最初にOption Explicitを記述して、
未定義の変数をエラーとして検出するようにしましょう。
dim 文のほかに、定数を定義する const や、class を作成した際に
class 外部から参照させないための private もあります。
なお、VBScript では、変数の型がありません。
dim var1 as string ' ← エラーになるVBScript では、
- 全てが
variant型で、代入した値や変数によって、型が変化します。 - また、数値型や文字列型とは自動で変換されます。
- object 型とその他を明確に区別したい場合は、その型の値を代入します。
isempty(変数名)
isnull(変数名)
isobject(変数名)
変数名 is nothing| 値 | 意味 |
|---|---|
| Empty | 変数の初期状態。何か代入するとその値の型になる(型名は TypeName 関数で取得) |
| Null | 「値が無い」ことを表す値。代入もできる |
| Nothing | オブジェクト参照が無い状態。isobject は True を返す |
dim str1
if isempty(str1) then print "str1 is empty"
str1 = 123
if NOT isempty(str1) then print "str1 is not empty. is " & typename(str1)
set obj1 = nothing
if isobject(obj1) then print "is object"
if obj1 is nothing then print "is nothing"- 関数を定義する際、戻り値がある場合は、戻り値の型が値かオブジェクトかで、
呼び出し元での代入文が変わりますので、どちらを返すのか決めて設計しましょう。 - 関数への引数では、値とオブジェクトのどちらでも受け入れる場合は、
isobjectの真偽を確認して場合わけをします。
function add(dims, e)
Redim Preserve dims( ubound(dims) +1 )
if isobject(e) then
set dims( ubound(dims) ) = e
else
dims( ubound(dims) ) = e
end if
end function
dim arr
arr = array() ' 要素0個の配列
add arr, "123" ' 文字列を追加
add arr, fso ' オブジェクトを追加- 数値と数字は、使用する場所によって、数値だったり文字列だったりします。
- できるだけ、意識して使い分けましょう。
| 関数 | 内容 |
|---|---|
cint() |
16 bit 整数に変換 |
clng() |
32 bit 整数に変換 |
int() |
int に切り捨て |
str1 = "456"
int1 = cint(str1)
long1 = clng(str1)
int2 = int(int1/10) ' 45(45.6 を切捨て)
int3 = cint(int1/10) ' 46(45.6 を四捨五入)
int4 = str1 + 123 ' 579
str4 = str1 + "123" ' "456123"補足(
+は使わない): 上の例が示す通り、
+はオペランドの型によって加算にも連結にもなる。
文字列連結には必ず&を使うこと。
またcint()は 16 bit(-32768〜32767)なので、
32768 以上でオーバーフローする点に注意。
- 文字も文字列も
" "で囲んで記述します。"自身は""として記述します。 -
&は文字列を連結する演算子です。数値や数字は文字列に変換して連結します。 -
midは文字列の一部を返します。mid(文字列, 開始位置, 長さ) - VBScript 内部では、文字列は Unicode で表現されているので、半角 / 全角の区別はありません。
- VBScript には、文字列と文字の区別はありません。長さ 1 の文字列で代用します。
str1 = "123456"
str2 = mid(str1,3,1)
str3 = """123""と""456"""
str2 = chr(9)
str3 = "これは\0で区切っています" & chr(0) & "続きもある"移行メモ(正誤): 元ページは
midの「開始位置は 0 が 1 文字目」
と記載していたが、VBScript のMidは 1 始まりである
(Mid("123456", 3, 1)は"3"を返す)。
後述のinstrも 1 始まりで、両者は整合している。
-
if文は、thenの右に処理を 1 つ書くか、thenの下の行に処理を複数行書きます。-
thenの右に書いたときは、end ifは省略できます。 -
thenの下に書いたときは、elseifかelseで続けて、end ifで閉じます。
-
str4 = "これはどんな文字列かな"
if mid(str4,3,1) = "ど" then print "「ど」があるね"
if instr(str4,"文字") >= len(str4)/2 then
print "後半に ""文字"" がある"
end ifVBScript の if 文は、式を全て評価してから、if 文全体の真偽を判定します。
set obj = func1()
if (NOT obj is nothing) and obj.flag = 2 then
' foo
end ifこの例の場合、obj がオブジェクトであっても、なくても .flag を参照するので、
obj がオブジェクトでなかった場合に、エラーになります。
下の様に、if 文をネストさせて、式の評価順に依存しないようにします。
if NOT obj is nothing then
if obj.flag = 2 then
' foo
end if
end if補足: これは「短絡評価(ショートサーキット)が無い」という意味である。
C# の&&/||や PowerShell の-and/-orは
短絡評価されるため、この書き分けは不要になる。
VBScript 固有の注意点として押さえておきたい。
VBScript では、「 _」で次の行へ継続(_ の前にスペースあり)、
「'」があると行末まで無視します。
str1 = "あいうえお"
str2 = mid (str1, _
instr(str1, "う") -1 ) ' "う" 以後の文字列を取り出すinstr は、文字列を含む位置を返します(1〜、含まないなら 0)。
ファイル操作は、Scripting.FileSystemObject を使用します。
const ForReading = 1
set fso = CreateObject("Scripting.FileSystemObject")
set ts = fso.OpenTextFile("c:\temp\tempfile.txt", ForReading)
print ts.readall
ts.close
set ts = nothing
set fso = nothing-
Scripting.FileSystemObjectによるファイル操作は、テキストファイルのみ動作します。 - 文字コードは Windows 既定、Unicode を指定できますが、
UTF-8 の様な文字コードは扱えません。 - バイナリデータも、
chr(10)の様に文字コードを指定した文字列として扱うことは
可能ですが、ファイル入出力時に、改行コードや BOM 文字、EOF 文字が処理されて、
期待するバイナリファイルにならないことがあります。
補足(UTF-8 とバイナリの扱い): この制限は VBScript の実務上の
最大の壁である。回避策としては次が使われてきた。
用途 手段 UTF-8 の読み書き ADODB.Stream(Charset = "UTF-8")バイナリの読み書き ADODB.Stream(Type = adTypeBinary)ただし
ADODB.Streamは BOM の扱いに癖がある。
PowerShell ならGet-Content -Encoding utf8で済む話であり、
これも移行の動機になる。
-
エラーは、自分で値チェックなどで検出する論理エラーのほか、
WSH その他が発生させるランタイムエラーがあります。 -
ランタイムエラーが発生すると、WSH そのものがエラー終了します。
-
COM などのオブジェクト呼び出しの先でエラーが発生した場合も、ランタイムエラーになります。
-
ランタイムエラーを VBScript 内で処理するには、
on errorを使います。-
on error goto 0(VBScript をエラー終了する) -
on error resume next(無視して続行、Err変数にエラー番号が設定される)
-
err1 = 0 ' エラー番号
on error resume next ' ランタイムエラーでVBScriptを終了させない
Err.Clear ' Err変数をクリア
set obj1 = CreateObject("hogehoge.hogehoge1")
if Err.Number <> 0 then err1 = Err.Number ' ランタイムエラー判定
if err1 = 0 then
if obj1.hagehage("てすと") <> 0 then
err1 = 1 ' 論理エラー
end if
end if
if err1 <> 0 then
print "エラー発生 " & err1
end if
wscript.quit err1 ' エラー番号 を VBScriptの終了コードに補足(
On Error Resume Nextの危険): これは
「以降すべてのエラーを黙って無視する」指定であり、
必要な範囲の直後でOn Error GoTo 0に戻すのが鉄則である。
スクリプト冒頭に書いたまま放置すると、
想定外のエラーも握り潰され、誤った結果のまま正常終了する。
VBScript のデバッグは、
- debug 用
print文を埋め込み - Visual Studio などの開発ツール
- Debugger —
cscript.exeで実行するときに//xをオプションに指定すると、
debugger が起動して、ステップ実行、変数の確認などができます。
| メソッド | 出力先 |
|---|---|
wscript.echo |
標準出力(cscript 時)または画面(wscript 時) |
wscript.stdout.writeline |
標準出力のみ。cscript.exe でのみ動作(wscript.exe ではエラー) |
画面の場合は、wscript.echo 1 つにつきメッセージボックスが 1 つ表示され、
[OK] を押すのを待ちます。
スクリプトで作り込む際には、下の様に、print 関数を定義する、などするといいでしょう。
sub print(v)
wscript.stdout.writeline v
end sub- VBScript - Wikipedia
https://ja.wikipedia.org/wiki/VBScript
- VBScript ランゲージ リファレンス
https://learn.microsoft.com/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/d1wf56tt(v=vs.84) - Windows Script Host の基礎 / オブジェクト モデル(WSH)
- FileSystemObject オブジェクト
https://learn.microsoft.com/office/vba/language/reference/user-interface-help/filesystemobject-object
-
チェック式WSH入門(全19回)
http://www.atmarkit.co.jp/fwin2k/tutor/cformwsh01/cformwsh01_01.html- VBScript の基本 / 関数 / データ型 / 配列 / Sub / Function / オブジェクト
- WScript / WshShell / WshNetwork / FileSystemObject / TextStream / Dictionary
-
Windows管理者のためのWindows Script Host入門(全11回)
http://www.atmarkit.co.jp/fwin2k/operation/wsh01/wsh01_01.html- WSH の内部構造 / コーディングの第 1 歩 / 各オブジェクトの詳細 / ファイル操作
Tags: 移行, シェル, インフラストラクチャ, Windows, Visual Basic, 移行