VBS
VBS(Visual Basic Script)メモの目次
- VBS(Visual Basic Script)メモの目次
- VBSとは?
- 自分の使ってるVBScriptのバージョンは?
- 各環境での記述方法など
- データベースへの接続
- タイプライブラリについて
- エラー処理と解除
- おすすめのエディタ、デバッグ環境
- ファイル選択ダイアログを使いたい
- フォルダ選択ダイアログ
- プログラムの強制終了
- 月末の日付を求める
- VBSのユーザインターフェース
- スペシャルフォルダー
- 配列のSort(並べ替え)
- 関数のリファレンスを使う!!
- 配列を動的に変更しながらデータを格納する
- ドラッグ&ドロップアプリケーション
- VBSのソースコードをエンコードしたい
- 数字を3桁ごとにカンマ区切りしたい
- 文字列をバイト単位で扱う関数
- バイナリデータの読み書き
- イベントを処理する
- 巨大な数値を扱う
- カレントディレクトリを取得したい
- カレントドライブを取得したい
- CD-ROMがセットされているかどうかチェックする
- 指定ディレクトリ以下の全てのファイルに対して処理する
- おまけアルゴリズム
VBSとは?
Visual Basic Scriptは、MicrosoftのVisual Basicシリーズの1つで、HTML(IE)、ASP、WSHなど色々な環境で動作するスクリプト処理を可能にしています。VBやVBAなどと基本的な構文が同じですので、VBやVBAを使っている人には簡単に理解することができます。WinのIE5.0以上がインストールされていれば、VBS5.0以上のバージョンがすでに組み込まれているはずですので、インストールの必要はありません。最新版を使用したいときは、Windows Scriptからダウンロードしてセットアップしましょう。
自分の使ってるVBScriptのバージョンは?
拡張子.vbs の適当なファイルを作成して、以下をコピーしてダブルクリックしてください。
Option Explicit ' getver.vbs - VBScriptのバージョン取得 MsgBox ScriptEngineMajorVersion & "." & ScriptEngineMinorVersion
各環境での記述方法など
上の例では、直接 VBS ファイルにアクセスしていますが、HTMLやASPファイルでの記述方法も書いておきます。
HTMLファイル(IEで表示の場合)
<SCRIPT>タグ内に記述します。
<HTML> <HEAD> <TITLE>VBScriptのバージョン表示</TITLE> <HEAD> <BODY> スクリプトのバージョンは、 <SCRIPT language="VBScript"> document.write ScriptEngineMajorVersion & "." & ScriptEngineMinorVersion </SCRIPT> です。 </BODY> </HTML>
ASP(PWS/IISサーバ経由)
<% ... %> で挟まれた部分がサーバーサイドスクリプトとして認識実行されます。<%= ... %> とイコールを付けるとその値をその場所に代入します。アクセスはPWS/IIS経由ですので単純にダブルクリックしてもだめです。http://localhost/.../.../getver.asp のようにアクセスします。
<%@ LANGUAGE="VBScript" %> <HTML> <HEAD> <TITLE>VBScriptのバージョン表示</TITLE> </HEAD> <BODY> スクリプトのバージョンは、 <%= ScriptEngineMajorVersion & "." & ScriptEngineMinorVersion %> です。 </BODY> </HTML> </HEAD>
データベースへの接続
一番手軽なのは、UDLを使う方法だ。UDLについては別のページに記載します。
Option Explicit ' 簡単なADODB接続&レコードセット取得 Dim objRec Set objRec = CreateObject("ADODB.RecordSet") objRec.Open "SELECT * FROM 仕入先", "File Name=Sample.udl" '... 処理 ... objRec.Close Set objRec = Nothing
というようにレコードセットを取得しデータベース処理を行います。上記は Sample.udl で指定されたデータベースから仕入先テーブルのすべてをレコードセットとして取得します。
タイプライブラリについて
忘れてた。タイプライブラリのこと書かないと、上のプログラム生VBSで実行してもエラーになっちゃうですます。はい。
adOpenStatic, adLockReadOnly, adCmdTableDirect とかっていうのはADO用の定数で、ADOのタイプライブラリを読み込むと使えるようになるです。adovbs.inc というのをHDD内から検索してみてください。そしてテキストなので開いてみましょう。非常に沢山の定数が定義されてますねぇ・・・。
生VBS(.vbs)では、インクルードできないので、必要な定数定義をプログラム内にコピーするか、定数を数字で直接書きます。もしくは、.wsf ファイルにしてタイプライブラリを参照します。
<job id="IncludeTest"> <reference object="ADODB.Recordset" /> <script language="VBScript"> ここにVBScriptを記述します。 </script> </job>
上記例では、ADOタイプライブラリを参照します。
またASPの場合は、METADATAでTypelibの宣言を行います。タイプライブラリは共通で利用するものなので通常global.asaで宣言しますが、.asp内で個別に宣言しても利用できます。
ライブラリID
<!-- METADATA TYPE="TypeLib" UUID="00000205-0000-0010-8000-00AA006D2EA4"-->
か、ファイル名
<!-- METADATA TYPE="TypeLib" FILE="C:\Program Files\Common Files\System\ado\msado15.dll"-->
や、
<!-- METADATA TYPE="TypeLib" FILE="C:\Program Files\Common Files\System\ado\msado25.tlb"-->
などと指定します。上記は全てADO2.5タイプライブラリを利用します。
エラー処理と解除
通常VBSで実行時エラーが発生すると、エラーダイアログが表示されプログラムの実行が中断されますが、
On Error Resume Next
を指定すると、以降エラーが出ても止まらずに処理を続けます。この時、Errオブジェクトには、適切なエラー値がセットされますので、それを参照、取得するようにします。例えば、このようにします。
If Err Then MsgBox Err.Description, vbCritical, "エラーNo." & Err WScript.Quit End If
ところで、このOn Error Resume Nextを一度設定してしまうと、以降実行時エラーが発生しても中断せずに処理を行ってしまいます。これを解除するには、
On Error Goto 0
と指定します。下記サンプルは、エラー(ゼロで除算)を2回しています。1度目のエラー処理で独自にエラーの説明ダイアログを出しています。2度目はエラー処理をしないで、実行時エラーのダイアログが表示されます。
Option Explicit ' error.vbs - エラー処理 On Error Resume Next Dim Kotae, Shiki Shiki = "5 / 0" Kotae = Eval(Shiki) If Err Then MsgBox Err.Description, vbCritical, "エラーNo." & Err ' WScript.Quit Else MsgBox Shiki & " = " & Kotae & " です",, "計算結果" End If On Error Goto 0 Kotae = Eval(Shiki) ' 実行時エラー
おすすめのエディタ、デバッグ環境
VBSなどHTMLスクリプトのデバッグをサポートしているエディタでオススメは、MS Officeに付属しているスクリプトエディタです。htmlのタグエディタの機能を合わせ持っているので、タグ入力は非常に楽です。
オフィスアプリからしか呼び出せないと思われがちですが、OfficeのディレクトリにちゃんとExeファイルがあり、単体で動作します。Windows98ではパスを変更していなければC:\Program Files\Microsoft Office\Office10\MSE7.EXE にセットアップされます。ない場合、MSE7.exe を検索してください。
インストールされてない場合は、インストールの必要があります。Officeアプリから、[ツール]->[マクロ]->Script Editor を選択すると、インストールするか聞いてきますので、そのままインストールしましょう。
.vbs をデバッグしたい場合は、スクリプトを<script>タグで挟んでからデバッグ実行します。基本的にこのデバッグは、HTMLスクリプトのデバッグなので、ブラウザ上で実行できるような形にしてあげる必要があるからです。
<script language="VBScript"> .... .... ここにVBSを記述します。 .... </script>
オフィスを持っていない場合は、Microsoft Script Debugger というソフトがMicrosoftから無償で提供されています。http://www.microsoft.com/japan/msdn/scriptingからダウンロードできます。
ファイル選択ダイアログを使いたい
このダイアログを利用するにはVisualBasicのライセンスが必要です。参考: http://tuka.s12.xrea.com/index.xcg?page=BBS%2D%BB%A8%C3%CC%2F33
コモンダイアログコントロールを使います。
Option Explicit Dim objDlg Set objDlg = WScript.CreateObject("MSComDlg.CommonDialog") With objDlg .Filter = "All Files (*.*)|*.*" .MaxFileSize = 256 .CancelError = false .ShowOpen MsgBox .Filename End With Set objDlg = Nothing
保存用なら、ShowOpen ではなく、ShowSaveを使います。
フォルダ選択ダイアログ
ShellオブジェクトのBrowseForFolderメソッドを使う方法です。このメソッドは選択されたフォルダをFolderオブジェクトとして返します。以下は選択されたフォルダを単純に表示するサンプルです。
Option Explicit ' selfolder.vbs - フォルダ選択ダイアログサンプル Const BIF_RETURNONLYFSDIRS = &H1 Const BIF_DONTGOBELOWDOMAIN = &H2 Const BIF_STATUSTEXT = &H4 Const BIF_RETURNFSANCESTORS = &H8 Const BIF_EDITBOX = &H10 Const BIF_VALIDATE = &H20 Const BIF_BROWSEFORCOMPUTER = &H1000 Const BIF_BROWSEFORPRINTER = &H2000 Const BIF_BROWSEINCLUDEFILES = &H4000 Dim objSA, objFol Set objSA = WScript.CreateObject("Shell.Application") Set objFol = objSA.BrowseForFolder(0, "フォルダを選択するのだ!", BIF_EDITBOX) WScript.Echo objFol.Items.Item.Path Set objSA = Nothing
詳しい情報は、MSDNに掲載されています。
プログラムの強制終了
プログラムの途中で強制的に終了したいことがあります。例えば、エラー処理の後にすぐに終了したい場合などです。
WScript.Quit
と記述します。
月末の日付を求める
マニュアルに詳しく記載されていますが、該当月の翌月の初日の前日 が月末となります。初日の前日は、1-1=0 です。
Option Explicit ' LastDay.vbs - 今月末を求める Dim LastDay LastDay = DateSerial(Year(Date), Month(Date)+1, 0) MsgBox LastDay
VBSのユーザインターフェース
VBSは色々な場面で利用できますが、このページに載せているVBSはフォーム等のユーザインターフェースがありません。なぜならVBS自体はユーザインターフェースの機能を殆ど持たないからです。普通の命令で利用できるのは、ダイアログ(MsgBox)やインプットボックス(InputBox)だけです。
フォームなどのユーザインターフェースを利用するには、ASPやIE(HTML)を使うことになります。各技術ごとの制限などは以下です。
拡張子 | ブラウザ | 制限など | ||
---|---|---|---|---|
ASP | .asp | なんでも可 | IIS/PWS経由でアクセスしなければならない | |
HTML | .htm .html | IEのみ | FileSystemObjectなどセキュリティ上好ましくない機能は利用できない | |
WSH | .wsf .vbs | - | GUIを持たない | |
HTA | .hta | IEのみ | セキュリティ上好ましくない機能も利用できる:-) |
このうちHTAは非常に便利でスピードこそ劣りますが、実行形式(.exe)ファイルのように殆ど制限のない単体のアプリケーションを作成することができます。.exe のインタプリタ版といったところでしょうか。
スペシャルフォルダー
OSのバージョンや個人の設定に依存してしまうものとして、スペシャルフォルダーがあります。マイドキュメントやデスクトップなどがそれにあたりますが、これらのスペシャルフォルダーを動的に取得し使用することで、環境に左右されにくいスクリプトを書くことができます。たとえば、デスクトップにショートカットを作成するようなスクリプトなどに利用します。
Option Explicit Dim props(15) props(0) = "AllUsersDesktop" props(1) = "AllUsersStartMenu" props(2) = "AllUsersPrograms" props(3) = "AllUsersStartup" props(4) = "Desktop" props(5) = "Favorites" props(6) = "Fonts" props(7) = "MyDocuments" props(8) = "NetHood" props(9) = "PrintHood" props(10) = "Programs" props(11) = "Recent" props(12) = "SendTo" props(13) = "StartMenu" props(14) = "Startup" props(15) = "Templates" Dim objWS Set objWS = CreateObject("WScript.Shell") Dim prop For Each prop In props MsgBox prop & vbCr & objWS.SpecialFolders(prop) Next Set objWS = Nothing
上記サンプルは、スペシャルフォルダーを1つずつメッセージボックスに表示していきます。
配列のSort(並べ替え)
悲しいことにVBScriptにはソートする関数が用意されていません。しかしながら世には優れたコンポーネントが沢山ありますので、そのようなコンポーネントを利用すれば実装は簡単です。しかしながら、レジストリを汚したくないとか、インストールが煩わしいとか、クライアントのマシンにインストールできないとか理由は色々あると思いますが、単純なソートの為にに態々コンポーネントを利用したくないこともあります。
そんな場合は、ソートの関数を自作しましょう。クイックソートはアルゴリズムが単純でしかも高速です。スクリプトレベルで実装しても高速で実用的だと思います。
クイックソートのアルゴリズムの簡単な概念は次のようになります。
- 配列要素を元に基準値を選択する(今回は引数配列の先頭要素)
- 基準値を境に基準値より小さいものを配列前方に、大きいものを後方に分割する
- 分割された配列に対してこれを繰り返す(再帰処理)
Option Explicit ' qsort.vbs - 配列のクイックソート ' 配列エントリのサンプル Dim entry entry = Array(53, 32, 98, 83, 38, 27, 10, 92, 33, 45) 'entry = Array("こ","ん","に","ち","わ","せ","か","い","!") ' ソート前後の配列内容を表示するテスト dispArray entry qsort entry dispArray entry ' クイックソートのインターフェース Sub qsort(array) quicksort array, 0, UBound(array) End Sub ' クイックソート本体(再帰) Sub quicksort(array, first, last) Dim point, f, l, tmp point = array(first) f = first: l = last Do While array(f) < point: f = f + 1: Wend While array(l) > point: l = l - 1: Wend If f >= l Then Exit Do tmp = array(f): array(f) = array(l): array(l) = tmp f = f + 1: l = l - 1 Loop If first < f - 1 Then quicksort array, first, f - 1 If l + 1 < last Then quicksort array, l + 1, last End Sub ' 配列内容を表示する Sub dispArray(datas) Dim data, str For Each data In datas str = str & data & vbCr Next MsgBox str End Sub
関数のリファレンスを使う!!
関数のリファレンスを使ったちょっと高度なテクニックです。マニュアルを見るとGetRef()は、関数をDHTMLのイベントと接続し、イベントが発生すると指定した関数が実行される例が載っていました。
果たしてイベントにしか利用できないのか?と思い実験してみたところ、変数にも格納できることがわかりました。
Option Explicit ' GetRef.vbs - GetRef()のテスト Dim objRef Set objRef = GetRef("Hello") objRef("Hoge") Sub Hello(str) MsgBox "Hello " & str & "!" End Sub
とこのように変数に関数へのリファレンスを格納して、呼び出すことができます。さらに発展させて、ハッシュに関数へのリファレンスを格納することもできました。
Option Explicit ' hashref - 関数リファレンスをハッシュへ格納するテスト ' Windows98SE, VBScript5.6 で動作確認 Dim objDic Set objDic = CreateObject("Scripting.Dictionary") ' 関数へのリファレンスのハッシュ objDic.Add "名前を聞く", GetRef("inputName") objDic.Add "名前を表示", GetRef("showName") ' 関数呼び出しテスト Dim strName strName = objDic("名前を聞く")() objDic("名前を表示")(strName) Set objDic = Nothing Function inputName inputName = InputBox("あなたの名前は?") End Function Sub showName(name) MsgBox "あなたの名前は" & name & "です。" End Sub
とこのようになります。引数の無いプロシージャの場合は、objDic("名前を聞く")()のように空の()を使用します。
配列を動的に変更しながらデータを格納する
配列を動的に変更するメリットは、
- 実行時にならないと使用する配列サイズがわからなくても大丈夫
- 配列が使っていたメモリを解放できる
などがあります。
VBSctiptでは、配列を動的に変更するのにReDimというステートメントを使います。「最低10個の配列は必ず必要」とか決まっているなら、単純に ReDim hoge(9) などとやってしまえばよいですが、決まっていない場合は、一度空の配列を作成してからReDimします。
また実際の処理では、なんらかのデータを読み込みながら配列に格納したり、規則的な計算で演算結果を配列に格納したりする場合など、ループを使うことが多いと思います。そういった場合、UBound(hoge)で配列インデックスの最大値を求めてから、ループごとに+1することで次に作成するインデックスを取得できます。
動的に作成した配列は、Eraseを使うとメモリを解放することができます。使わなくなった配列は小まめにメモリ解放してあげましょう。
下記サンプルは、hoge.vbs の内容を配列に一行づず格納し、結果を一行ずつ配列から読み取り表示します。
Option Explicit ' 配列を動的に変更しながらデータを格納する Const FileName = "hoge.vbs" Dim objFS, objTS Set objFS = CreateObject("Scripting.FileSystemObject") Set objTS = objFS.OpenTextFile(FileName) ' 配列を動的に変更しながらデータを格納する Dim strLines, n strLines = Array Do Until objTS.atEndOfStream n = UBound(strLines) + 1 ReDim Preserve strLines(n) strLines(n) = objTS.ReadLine Loop Set objFS = Nothing ' 配列の内容を順番に表示する Dim strLine For Each strLine In strLines WScript.Echo strLine Next Erase strLines
ドラッグ&ドロップアプリケーション
VBS(WSH)ではドラッグ アンド ドロップがサポートされていますが、ドロップできるファイル数に制限があるので結構ショボイです。マニュアルによると、
スクリプトにドラッグできるファイルの数は、システムで許容されるコマンド ラインの長さの上限によって決まります。ドラッグしたファイル名をすべて合わせた文字数がコマンドラインの長さ制限を超えていると、ドラッグ アンド ドロップ操作が失敗します。
だそうです。試しにデフォルトの設定で10ファイルくらいドラッグ&ドロップしたらエラーがでました。ありゃりゃ。:-( これを踏まえてドロップするファイルは、是非、浅い階層で短いフォルダ名に入れておきましょう!・・・オイオイ。
まあでも、そのことに目を瞑れば取得も簡単で結構便利です。
サンプルは、ドロップしたファイルのリードオンリー属性を反転します。おー、このソフト結構便利かも。:-P
Option Explicit ' revro.vbs - ドロップしたファイルのリードオンリー属性を反転する Dim objArgs, strPath Set objArgs = WScript.Arguments Dim objFS, objFile Set objFS = CreateObject("Scripting.FileSystemObject") For Each strPath In objArgs Set objFile = objFS.GetFile(strPath) objFile.Attributes = objFile.Attributes Xor 1 Next Set objFS = Nothing
VBSのソースコードをエンコードしたい
Microsoftから無償でダウンロードできるScript Encoderを使います。以下からダウンロードできます。
使い方はScript Encoderのマニュアルに書かれていますが、以前VBScriptのエンコードでちょっとハマッたので、それだけ紹介しておきます。
生VBSファイル(拡張子.vbs)をエンコードするには、アウトプットファイル名の拡張子を.vbeにします。
screnc hoge.vbs hoge.vbe
生成されたhoge.vbeファイルはそのままhoge.vbsと同様に動作します。
数字を3桁ごとにカンマ区切りしたい
文字列中から数字を探して、3桁ごとにカンマ区切りする方法です。
与えられた文字列を逆さまにしてから3桁数値ごとにマッチさせます。その際、肯定先読み(?=\d)を使用して4桁目が存在する場合のみマッチさせます。これがないと、3桁や6桁の数値の先頭にカンマが入ってしまいます。
置換の終わった文字列は再度逆さまにして元に戻します。
Option Explicit ' 3figure.vbs - 数字を3桁ごとにカンマ区切り Dim objRE, Num Num = "この車は2150000円しました。1000台限りの限定発売でした。" Set objRE = New RegExp objRE.Pattern = "(\d\d\d)(?=\d)" objRE.Global = True Num = StrReverse(objRE.Replace(StrReverse(Num), "$1,")) Set objRE = Nothing WScript.Echo Num
また、単純に数値だけであれば、FormatNumber関数を使うと簡単です。
Num = 1000000 WScript.Echo FormatNumber(Num, False, False, False, True)
文字列をバイト単位で扱う関数
文字列をバイト単位で扱う関数です。マニュアルの片隅にちょこっとだけ載っています。なぜこんな小さく載せているのかちょっと疑問です。VBAのマニュアルでは目次になっているのにねぇ・・・。
例えば、Lenは文字数ですが、LenBはByte数になります。
Option Explicit 'bytefunc.vbs Dim str str = "深夜でございます" WScript.Echo "文字数は" & Len(str) & "文字です" WScript.Echo "Byte数は" & LenB(str) & "Byteです" WScript.Echo Left(str, 2) & " - " & Mid(str, 3, 4) & " - " & Right(str, 2) WScript.Echo LeftB(str, 2) & " - " & MidB(str, 3, 4) & " - " & RightB(str, 2) WScript.Echo Asc("漢") WScript.Echo AscB("漢") & " - " & AscB(RightB("漢", 1)) WScript.Echo "Chr(-30017)は" & Chr(-30017) & "です" WScript.Echo "ChrB(34) & ChrB(111)は" & ChrB(34) & ChrB(111) & " です"
バイナリデータの読み書き
{{include ADO,バイナリデータの読み書き}}
イベントを処理する
VBSでイベントを使うには、WScript.CreateObject の第2引数にプリフィックスを指定します。プリフィックス_イベント名のような関数を定義すると、イベントが起こるとその関数が呼び出されます。
CreateObjectは3種類あり間違いやすいので注意が必要です。
- CreateObject
- WScript.CreateObject
- Server.CreateObject
このうちイベントに使うのは、WScriptオブジェクトのCreateObjectです。WScript.CreateObjectはWSHでしか利用できませんが、イベントと接続できます。Server.CreateObjectはASPのサーバスクリプト内で利用します。ただのCreateObjectは、普通にオブジェクトのインスタンスを作成したり、リモートのインスタンスを作成したりできます。
サンプルは、ADODB.Connection のイベントであるConnectCompleteとDisconnectを使っています。非同期接続を行い5秒後に接続を切ります。接続されるとCon_ConnectComplete が処理され、切断するとCon_Disconnect が処理されます。
Option Explicit ' adoev.vbs - ADOイベントをVBScriptで使ってみるテスト Dim objCon Set objCon = WScript.CreateObject("ADODB.Connection", "Con_") objCon.Open "File Name=nw.udl" , , , 16 WScript.Sleep 5000 objCon.Close Set objCon = Nothing Sub Con_ConnectComplete(ByVal pError, adStatus, ByVal pConnection) WScript.Echo "接続しちゃった!" End Sub Sub Con_Disconnect(adStatus, ByVal pConnection) WScript.Echo "切っちゃった!" End Sub
巨大な数値を扱う
世に言うBigIntです。実は仕事で必要となり本日急遽作成したものです。スクリプトでなくても良かったのですが、書いてみたら意外と早かったのでスクリプトのまま納める予定です。
さておき、このプログラムは正の2値の足し算ルーチンのみです。引数は当然ながら、文字列な数値となります。アルゴリズムは単純に1桁ずつ筆算するような感じです。
Option Explicit ' bigint.vbs - 巨大な数値を扱う Dim A, B A = "900750974388398729199701419182087930200787329829" B = "4127897100837491024712900874190749187491438878923" WScript.Echo BigInt_Add(A, B) Function BigInt_Add(X, Y) Dim aZ, i, iZ, iK, l, lX, lY lX = Len(X) lY = Len(Y) If lX > lY Then Y = String(lX - lY, "0") & Y l = lX Else X = String(lY - lX, "0") & X l = lY End If aZ = Array ReDim Preserve aZ(l) iK = 0 For i = l To 1 Step - 1 iZ = CInt(Mid(X, i, 1)) + CInt(Mid(Y, i, 1)) + iK If iZ >= 10 Then iZ = iZ - 10 iK = 1 Else iK = 0 End If aZ(i) = iZ Next If iK Then aZ(0) = 1 End If BigInt_Add = Join(aZ, "") Erase aZ End Function
上記サンプルでは省きましたが、BigIntな数値文字列でも、IsNumeric()で検査できるので、関数内か関数呼び出し前に簡単にチェックすることが可能です。例えば、
If Not (IsNumeric(X) And IsNumeric(Y)) Then WScript.Echo "引数は数値として評価できません" WScript.Quit End If
のようにチェックします。
カレントディレクトリを取得したい
GetFolder関数でカレント(".")を指定することで、カレントフォルダを取得できます。
Option Explicit ' cd.vbs - カレントディレクトリの取得 Dim objFol Set objFol = CreateObject("Scripting.FileSystemObject").GetFolder(".") WScript.Echo objFol.Path Set objFol = Nothing
カレントディレクトリの取得は何かと便利です。例えば、プログラム中で使用する外部ファイルを相対パスで指定することが可能です。下記サンプルは、カレントディレクトリのUDLファイルを指定するADOの接続文字列を生成します。このようにしておけば、.udlファイルと.vbs を違う場所に移動しても、プログラム中のパスを書き換えることなく利用できます。
Option Explicit ' cd2.vbs - カレントディレクトリの取得 Const UDL = "nw.udl" Dim objFS, objFol, strConn Set objFS = CreateObject("Scripting.FileSystemObject") Set objFol = objFS.GetFolder(".") strConn = "File Name=" & objFS.BuildPath(objFol.Path, UDL) Set objFol = Nothing Set objFS = Nothing WScript.Echo strConn
こっちの方がオシャレかな?WScript.ScriptFullName で実行ファイルのフルパスを取得し、GetParentFolderName でその親パス(つまりカレントディレクトリ)を取得します。
Option Explicit ' cd3.vbs - カレントディレクトリの取得 Dim objFS Set objFS = CreateObject("Scripting.FileSystemObject") WScript.Echo objFS.GetParentFolderName(WScript.ScriptFullName) Set objFS = Nothing
カレントドライブを取得したい
ついでにカレントドライブの取得も。上のコードとそっくり・・・:-)
Option Explicit ' curdrv.vbs - カレントドライブの取得 Dim objFS Set objFS = CreateObject("Scripting.FileSystemObject") WScript.Echo objFS.GetDriveName(WScript.ScriptFullName) Set objFS = Nothing
CD-ROMがセットされているかどうかチェックする
作成したプログラムをCD-Rに焼いて配布するとか言った場合、エンドユーザーの環境によってCDドライブの場所は違います。あるユーザーはDドライブだったり、あるユーザーはEドライブだったりします。そういう場合を考慮して、配布するCD-ROMのボリューム名で検索するようにします。指定したボリュームが見つからない場合(=CD-ROMがセットされていない)は処理を終了するようにします。
Option Explicit ' cdready.vbs - CD-ROMがセットされているかどうかチェックする Const CDROM = 4 Const VOLUME_NAME = "CDTITLE" Dim objFS, objDrv, strDrv Set objFS = CreateObject("Scripting.FileSystemObject") For Each objDrv In objFS.Drives With objDrv If .DriveType = CDROM And .VolumeName = VOLUME_NAME Then strDrv = .Path Exit For End If End With Next Set objFS = Nothing If IsEmpty(strDrv) Then MsgBox "CDをセットしてください!", vbCritical WScript.Quit End If ' ここからCDを使った処理を書く WScript.Echo strDrv & "ドライブにセットされてるよ!"
指定ディレクトリ以下の全てのファイルに対して処理する
Perl版しか書いてなかったんですねぇ。本日ASP開発で必要になったので作りました。再帰を使った単純な方法です。サンプルは、hoge以下の全てのファイル名を表示します。
Option Explicit ' filefind.vbs - 再帰ファイルサーチ Const FIND_DIR = "hoge" Dim strFileList Dim objFS, objFolder Set objFS = CreateObject("Scripting.FileSystemObject") Set objFolder = objFS.GetFolder(FIND_DIR) FileFind objFolder Set objFolder = Nothing Set objFS = Nothing WScript.Echo strFileList WScript.Quit Sub FileFind(objFolder) Dim objFile, objSubFolder For Each objFile In objFolder.Files strFileList = strFileList & objFile.Name & vbCrLf Next For Each objSubFolder In objFolder.SubFolders FileFind objSubFolder Next End Sub
おまけアルゴリズム
ユークリッドの互除法
最大公約数を求めるアルゴリズムとして有名なユークリッドの互除法のプログラムです。
Option Explicit ' ユークリッドの互除法(再帰版) Dim m, n m = 96 n = 128 MsgBox m & "と" & n & "の最大公約数は" & GCD(m, n) & "です" Function GCD(A, B) If A Mod B Then GCD = GCD(B, A Mod B) Else GCD = B End If End Function
再帰を使った方法が有名で見た目も非常に美しいですが、ループで処理したほうが実行速度は速いです。(こちらも意外と美しい:-P)
Function GCD(A, B) Dim C While B C = A Mod B: A = B: B = C Wend GCD = A End Function