Visual Basic 6.0を先取り!

Windows Scripting Hostのオブジェクトを活用する

酒井 法雄 SAKAI,Norio
norio@int21.co.jp


Visual Basicはバージョンを重ねるごとに,どんどん便利に,柔軟に,そして大きくなってきた.その一見大きくなった原因として,COMによるオブジェクトライブラリの増加がある.しかも,Visual BasicからOffice製品やIEなどのオブジェクトまでも操作することができる.
そういったオブジェクトの中では比較的新しいWindows Scripting Host(以下WSH)には,Visual Basic単体ではできない機能をカンタンに実現できる強力なライブラリが収められている.ここでは,WSHライブラリをVisual Basicから使ってみることにしよう.

書くことがない!?

「久々の登場の酒井法雄です.みなさん,お元気だったでしょうか」
と,思わず書いてしまった.Visual Basic Magazine創刊号から,主として特集を連載(?)してきた私だが,ここ数ヶ月お休みさせていただいた(といっても本業であるソフトウェア開発はしていた).それでも,ちゃんと特集記事はあったし,むしろ本誌は厚くなったほどである.
「これならまだしばらく休んでもいいかな」とも思ったのだが,読者の皆様からは,「最近,酒井さんの記事がありませんが,どうしたのですか.さびしいです」といったハガキが届いたという.本当にありがたいことである.私のような者を気にかけてくださる方もいらっしゃるのかと胸を熱くしつつ,久々の登場とあいなった(とはいえ,相変わらず遅い原稿で,編集部の皆様にはご迷惑をおかけっぱなしである).
 思えば,私がしばらく執筆しなくなったのは,これが初めてではない.Visual Basic Magazineが創刊される前,私は翔泳社のDr. Dobb's Journal JapanにVisual Basicの連載を長いあいだ執筆していた.そのときにも「もう書くことがない」という理由で,連載を中止したことがあった.当時の状況としては,長らく続いたVisual Basic 2.0を活用するためのほとんどあらゆることを書きまくり,日本では発売されなかったVisual Basic 3.0についても書きまくり,本当に書くことがなくなってしまったと感じたのである.そして,Visual Basic 4.0の発表が間近であり,いまさら古いことを書き連ねても意味がないと感じたのであった.
 今回のお休みの原因は,前回と同じだったのである.もちろん,細かい部分で私が書いていないことはたくさんあったが,Visual Basic自体の特徴を生かすことや,DLLが煩雑に変わる開発環境を考えると,書かなかったことのほとんどは「Visual Basicらしくないもの」や「怪しい」ことであり,書く気になれなかったのである.またしても「書きつくした」と感じたのだ.もちろん,私が似たようなことを繰り返し書くよりも,本誌には優れた記事を書くことができるライターが増えてきたから,そういう方にお任せしたほうがよいのではないかとも感じたのである.
 そして,そういうウマい時期に,MicrosoftはVisual Basic 6.0を発表してくれた.
 また,復帰しなくてはならない.Visual Basic 6.0英語版は,9月2日にリリース予定である.しかし,日本語版のVisual Basic 6.0の詳細について述べるには,まだちょっとだけ時期が早いようだ.

Windows Scripting Hostとは?

 そこで今回は,Visual Basic 6.0に搭載されるという,とっても便利なオブジェクトについて,ちょっと先取りして紹介することにしよう.大丈夫,Visual Basic 5.0からでもちゃんと使えるのである.というのも,このオブジェクトはすでにいろいろな形で配布されているのである.早い話が,そのオブジェクトが標準でVisual Basic 6.0のライブラリとして提供されることになったというワケである.
 そのオブジェクトとは,File System Objectと呼ばれるものである.これは,WSHとよばれるものに含まれている.WSHは,Option PackにIIS 4.0のデバッグや拡張機能用として搭載されているほか,Windows 98にも標準でインストールされる.また,単体としてhttp://www.asia.microsoft.com/Japan/Developer/Scripting/からダウンロードすることもできる.このへんにサンプルプログラムなどもあるから,いっしょにダウンロードしておこう.
 さて,ではWSHとは一体何なのだろうか?
 誤解を覚悟でカンタンに言えば,これはMS-DOSのころにさんざんお世話になったBATファイルの拡張版である.つまりスクリプトを書いてカンタンなプログラムを動かせるというものだ.
 BATファイルはcommand.comやcmd.exeといったコマンドインタープリタをベースに動くものだから,大したことはできない.だが,標準入出力をうまく使うような外部にあるコマンドを呼び出してやれば,かなりいろいろなことができるようになる.しかし,GUIの時代になっては,BATではどうにもならないことが出てきた.そこで,Windowsのもつ機能をスクリプトから呼び出せるようにした仕組みがWSHなのである.しかも,その言語仕様はVBScriptまたはJscriptである.
 ここでピーンときたアナタは偉い.そう,実際には,ここで使われているのも例によってCOMのアーキテクチャ,つまりActiveX Scripting Engineなのである.ActiveX Scripting Engineは,Microsoftがインターネット恐怖症に陥っていた2年ほど前にひねり出されたもので,Netscape陣営のJava Scriptに対抗するためのIE用スクリプトエンジンであった.しかも,特定の言語仕様に依存しないものであり,あるのはあくまでも言語モジュールへのインターフェイスである.Microsoftは,そこにVBScriptとJava Script(最近ではイロイロあってJScriptとよんでいるようだ)の言語エンジンが搭載されている.したがって,このインターフェイスに沿ったエンジンを作れば,どんな言語でも動かすことができてしまうわけである.
 しかし,せっかくこんな便利な機能を作ったものの,結局のところインターネットでVBScriptが流行ったなんて聞いたこともない.だが,このアーキテクチャ自体はとってもオモシロイ.そこで,私の会社(有限会社イント・ツーワン)では,コンソール周りを拡張すべくこのテクノロジーを作ったシステムを作ってしまった.題して,ASEXECである.
 このコマンドは,ActiveX Scripting Engineを呼び出し,VBScriptあるいはJScriptで記述されたスクリプトをコマンドラインから実行可能であり,実行結果もすべてコンソールに出力できる.しかも,ちゃんとコンソール用の制御オブジェクトまでも完備していた.WindowsのようなGUIしか考えていないお間抜けOSでは,リモート管理をマトモにすることはできない.そこで,ログインシェルとASEXECを組み合わせて,なんでもできるようにしちゃおうという企画だったのである.
 もちろん,皆様ご存じのように,GUIなんてものは初心者騙しに過ぎず,効率よい管理やオペレーションは,コマンドラインからやったほうが速いに決まっている.UNIXでtcshやbashを使っているときの,手が疲れないこと,オペレーションの効率がよいことといったら,Windowsなど比較すべくもない.本当にviを使っているときは心が安らぐ.で,そういうことができるようにしちゃおうと思ったのである.しかし,せっかく作ったものの,これを売り物にするでもなく,とりあえずはMS-DOSライクなしょうもないテキストベースのテニスゲームみたいなもんでも作って遊ぶ程度であった.
 Windowsの弱点を一番よく知っているのは,もちろんMicrosoftである.「これからはGUIだっ」とか言っていたようなお偉いさんはどうだか知らないが,少なくともマトモな技術者だったら,Windowsの管理なんてやりたくないと社内の人でも思ったに違いない.そこで,そういったコトをなんとかしようというので,WSHができたのである.
 はっきり言って,これは弊社製品をMicrosoftがマネっこしたに違いない.と思ったのだが,よくよく調べていくと,非公開ながらWSHのほうがちょっとだけ早くできていたらしい.ちっ.
 だが,コンソールオブジェクトまでサポートしているから,ウチのASEXECのほうが管理ツールなどをマトモに作れるに違いない.などと負け惜しみを言っていても始まらないので,続きを行こう.

WSHの使い方の例

図1:WSHスクリプトの実行画面例
(16KB)

 さて,上記URLからWSH10.EXEをダウンロードしたら,エクスプローラなどからダブルクリックする.そうすれば,あっけなくインストールが終了する.ついでにサンプルプログラムも同様にインストールしよう.
 ここにはいくつかのファイルがあるが,拡張子が「.VBS」がVBScriptのもの,「.js」がJScriptのサンプルである.すでにWSHインストール時にファイルの関連付けができているので,そのままダブルクリックして実行することもできる.しかし,本来は,コマンドラインからcscript.exeを実行し,引数としてスクリプトファイルを指定するというのが本当だ.

 また,GUI版としてwscript.exeも用意されている.
 これらのEXEは内部的には,wshom.ocxをコールしており,このActiveXコントロールの内部には,いろいろと役に立つ便利なオブジェクトが含まれているのである.また,同時にインストールされるscrrun.dllにも,主としてファイル操作をするための便利なオブジェクトが含まれている.つまり,WSHは単なるActiveX Scripting Engineを使うためのフロントエンドではなく,そこに同時に用意された便利なメソッドなどを使えるシステムなのである.
 ご存じの通り,VBScriptはいわゆるVBAのサブセットであり,外部にあるオブジェクトを操作することができる.ExcelでもAccessでも,Visual Basicで作ったコンポーネントでもOKだ.しかし,BAT処理みたいなことに役立つ関数がないことには意味がないのである.そこで,こういったオブジェクトが入っているというワケである.
 cscript.exeおよびwscript.exeについての詳細は,次のURLを参照していただきたい.

 もっとも,VBScriptはVisual Basicなどと比較して効率的なコーディング環境が調っているわけではないので,Visual Basic 5.0のようなクイックヒントやデバッグ環境などに慣れた身にとっては,こんなことやってられないと思うのであった.

WSHのオブジェクトモデル

 では,実際にはどのように便利な機能があるのだろうか.
 まずは,wshom.ocxとscrrun.dllをクイックビューアで見てると,それぞれ図のように大量なWindows APIがインポートされていることが分かる.つまり,これらのAPIを使った処理が含まれているというワケである(図2).
 ファイル関係やシェルAPI,ネットワークAPIなどが含まれており,いやがおうにも期待に胸は高鳴る.

図2:wshom.ocxとscrrun.dllをクイックビューアで見る

 

 実際にこれらのオブジェクトの内容を知るには,次のような方法で資料を得ることができる.

 wshom.ocxに含まれるオブジェクト
 wshom.ocxには,ShellとNetworkの2つのトップレベルオブジェクトが含まれている.これらのオブジェクトの詳細は,次のURLを参照していただきたい.

 なお,Visual Basicからwshom.ocx(Windows Scripting Host Object Model(Ver 1.0) )を参照設定しておけば,オブジェクトブラウザからその構造やメンバーを知ることができる.オブジェクト名は,IWshRuntimeLibraryがトップレベルである.
 Shellオブジェクトには,レジストリ操作やショートカット作成などShell API周りの関数が含まれている.Networkオブジェクトには,ネットワーク周りの操作ができる関数が含まれている.従来であればVisual BasicでもWindows APIの助けを借りなければならないものばかりである.

 scrrun.dllに含まれるオブジェクト
 このオブジェクトについては,次のURLにある「VBScriptランゲージリファレンス」から検索することができる.

図3:Windows Scripting Hostのオブジェクトモデル
(25KB)

 これと同じ内容のものはアーカイブされておらずダウンロードできないので,このURLから調べるしかない.
 VB5の参照設定でMicrosoft Scripting Runtimeを選んでおくと,F2キーでオブジェクトブラウザを起動しオブジェクト構造を知ることができる.ただし,現状のWSHとは定数値などが異なっているし,実際に動かしてみると動かないものもある.VB6付属のWSHだと動くのかもしれない.
 実際にこのオブジェクトに含まれるのは,FileSystemObjectである.ここにあるものは,ドライブ,フォルダ,ファイルに関する操作や情報取得の関数のほか,連想配列やテキストストリームなどの操作が含まれている.やはり,従来のVisual Basic単体ではできない機能が多く実現されている.
 実は,このFileSystemObjectこそが,Visual Basic 6.0に標準で搭載されるものなのである.ただし,細かい仕様などが同じであるかどうかは,まだ確認できていない.

 これらのオブジェクトの階層およびメンバーを図3に示す.
 いずれのオブジェクトも,その下の階層で使われているオブジェクトがあることに注意してほしい.DAOやRDOなどと同様に,オブジェクトの階層モデルを理解していないと,ちょっと使いにくい.たとえば,FileSystemObjectのOpenTextFileメソッドの戻り値は,TextStreamオブジェクトであり,そのReadLineメソッドを使って1行読み込むといった処理をしてゆくことになる.

便利なオブジェクトをVisual Basicから使う

 このように,これらのオブジェクトがもっている機能は,標準のVisual Basicでは実現できないものが多く,同じようなことを実現するためには,従来であればWindows API使いまくりになってしまった.ところが,こんなオブジェクトがタダで提供されているのである.これを使わない手はないだろう.
 しかも,VBScriptなどと違って,クイックヒントが装備されたエディタや,高機能なデバッガといった統合開発環境をもつVisual Basicから使えば,もっと効率的にプログラミングができる.逆に,Visual Basic環境を使って書いたソースをちょっとだけ書き直し,スクリプトとして保存して,cscript.exeから実行させるというワザさえあるのだ.これは便利そうである.
 次に,それぞれのモジュールごとにVisual Basicから使うための方法を述べよう.

 wshom.ocx
 このモジュールを使うには,いきなりCreateObjectでインスタンシングしてしまえばよい.

 ただし,前に述べたようにCreateObjectできるのは,ShellとNetworkの2つのオブジェクトだけであることに注意してほしい.
 もうひとつの方法は,先に述べたように「Windows Scripting Host Object Model (Ver 1.0)」を参照設定する方法だ.こうすればオブジェクト構造も見られ,エディタ上でヒントを出すことができる(図4).

        Dim WSHnetwork As New IWshShell_Class
        Dim WSHnetwork As New IWshNetwork_Class
    

 このほうが使いやすいが,オブジェクト名が気持ち悪い.

    ' 気持ち悪いけどクイックヒントが出るので便利
    Private Sub cmdGet_Click()
        Dim oNet As New IWshNetwork_Class
        Dim oCol As IWshCollection_Class
        Dim s As Variant
    
        Set oCol = oNet.EnumPrinterConnections
        Debug.Print oCol.Count
        For Each s In oCol
            lstPrt.AddItem s
        Next
    End Sub
    
    ' 気持ちよいけど不便
    Private Sub cmdGet2_Click()
        Dim oNet As Object
        Dim oCol As Object
        Dim s As Variant
    
        Set oNet = CreateObject("WScript.Network")
        Set oCol = oNet.EnumPrinterConnections
        Debug.Print oCol.Count
        For Each s In oCol
            lstPrt.AddItem s
        Next
    End Sub
    
図4:WSHのオブジェクト構造を閲覧する
(17KB)

 scrrun.dll
 「Microsoft Scripting Runtime」を参照設定すればよい(図5).
 オブジェクトブラウザでみると,「Scripting」にあるオブジェクトの内容を知ることができる(図6)

図5:「Microsoft Scripting Runtime」を参照設定する
(10KB)
図6:「Scripting」にあるオブジェクトを閲覧する
(14KB)

 ここまで分かれば,Visual Basicプログラミングでのオブジェクト階層に慣れたあなたなら,もうスグにでも使うことができるだろう.実際にどのようなことができるかという例として,いくつか紹介していくことにしよう.

ShellオブジェクトとNetworkオブジェクトの使用例

 まずは,ShellオブジェクトとNetworkオブジェクトである.これはちょうどMicrosoftのサイトにWSH用のサンプルがあったので,これをVisual Basicで動くように書き直してみたものなので,著作権はMicrosoftにある.このサンプルは,もともと別れていた4つのサンプルをひとつのフォームにまとめたものである.

図7:ショートカット作成のサンプル

図8:ネットワーク情報を見るサンプル

図9:レジストリキーを操作するサンプル

 ソースコードをリスト1に示す.大して難しいことはやっていないので,詳しくは,階層図を見ながら,ソースコードを眺めてほしい.しかしながら,このソースコードはきたない...

(リスト1)

FileSystemObjectの使用例1

 次に,FileSystemObjectを使ってみた.このオブジェクトには大きく分けると,ドライブ・フォルダ・ファイル情報に関するものと,連想配列,テキストストリームの3つの機能に分けられる.
 ここでは,最初のものについて,ひと通りの機能を使ってみた.次にそれぞれありがちな手法をプロシージャごとに紹介しよう.
 まずは,最初にFileSystemObjectをインスタンシングしておく.

 ドライブ一覧の取得
 ひとつのドライブはDriveオブジェクトに,それらのコレクションとしてのドライブ全部はDrivesコレクションである.次のコードは,すでにインスタンシングされているFileSystemObjectから,Drivesコレクションを作成し,お決まりのコレクションからオブジェクトをひとつずつ取得するものである.
 リストボックスには,ドライブ文字列Letterプロパティ,IsReadyプロパティの内容によって適切な文字列,そしてファイルシステムFileSystemプロパティを表示している.

 ドライブの詳細情報取得
 ドライブ一覧のリストボックスから特定のドライブが選ばれたら,その詳細を表示し,さらにそのドライブ内のフォルダ一覧を取得する.
 ここでは,それぞれを別のプロシージャとし,引数としてそれぞれドライブ文字列とルートフォルダのFolderオブジェクトを渡している.

 ドライブレターをもとにして,Drivesコレクションの連想配列で選ばれたDriveオブジェクトを得る.そのあとは単純にDriveオブジェクトのプロパティを表示している.エラートラップは,準備できていないドライブなどの場合のエラーを防ぐためのものである.

 フォルダの一覧取得
 引数であるフォルダを示すFolderオブジェクトから,フルパス名Pathプロパティを得て,リストボックスに追加している.その後,引数フォルダ下のサブフォルダSubFoldersコレクションから,その下にあるフォルダ一覧を得ている.
 ここで注意してほしいのは,この関数DispFoldersはリカーシブ(再帰)して呼ばれていることだ.最初の引数oFolderは「C:\」のようなルートフォルダである.つまり,ルートフォルダ以下にあるフォルダをすべて得て,それぞれのフォルダについて再び自分自身を呼び出している.こうすれば,さらに下のフォルダまですべてをリストボックスに追加できるというわけだ.
 従来のVisual BasicのDir関数でも同様のことができたが,ここまできれいに書くことはできなかった.きれいに書くことができるということは,プログラマにとって,とても嬉しいことである.

 フォルダの詳細情報取得
 フォルダ一覧のリストボックスから特定のフォルダが選ばれると,そのフォルダについての詳細情報を表示し,さらにそのフォルダに含まれるファイルの一覧を表示する.
 先ほどと同様,それぞれはプロシージャとして作成されており,引数はFolder型およびFilesコレクションになっている.

 引数であるFolderオブジェクトについて,プロパティを表示している.どんなプロパティがあるかチェックしておこう.

 ファイルの一覧取得
 ファイルの一覧は,引数であるFilesコレクションをもとにして,リストボックスに追加している.

 ファイルの詳細情報取得
 ファイルの詳細表示は,やはりプロパティを表示しているのみ.どんなプロパティがあるかチェックしておこう.
 コメントにあるように,ファイルをコピー,削除,移動をするメソッドも用意されている.

 ファイルの作成・アクセス・修正日時の取得
 ファイルおよびフォルダには,DateCreated,DateLastAccessed,DateLastModifiedの各プロパティがあり,それぞれファイルの作成日時,最後にアクセスされた日時,最後に修正された日時を知ることができる.
 したがって,特定フォルダ下にあるあまりアクセスされていないファイルを探し出して消すといったことができる.ここでは,指定されたドライブにあるこうしたファイルを探し出すコードを作成してみた(リスト2・図10).
 ただし,フォルダについて,これらのプロパティを正常に取得することはできなかった.もしかすると私のコーディングが悪いのかもしれないが,ほかにもいくつか正常に動作しないものがあった.これらがVisual Basic 6.0で改善されていることを望みたい.

(リスト2)

図10:指定されたドライブにあるファイルを探すサンプル
(20KB)

FileSystemObjectの使用例2

 最後は,連想配列とテキストストリームを使ってみよう.
 連想配列は,すでにコレクションなどでおなじみのように,キーとなる文字列などから対応するアイテムを得るというものだ.配列などと違って,数値ではなく文字列から検索できることがウリである.
 これは,それこそCollectionオブジェクトをうまく使えば実現することもできるが,FileSystemObjectのDictionaryオブジェクトを使えば,もっとカンタンに使いこなすことができる.
 また,テキストファイルの読み書きをするTextStreamオブジェクトもある.そこで,ここではDictionaryオブジェクトに含まれた内容をTextStreamオブジェクトを使ってファイルに保存したり,読み込んだりするプログラムを作ってみた.
 まずは,Dictionaryオブジェクトをインスタンシングしておく.

 連想配列への追加
 DictionaryオブジェクトoDicは,すでに汎用コレクションそのものである.追加は,Addメソッドを使い,引数としてキーと対応するアイテムを渡せばよい.
 ここでは,テキストボックスに入力されたものを追加している.

 いちいち文字列を入れるのも面倒なので,Form_Load時に月を表わす短い文字列,たとえば「Jan」をキー,長い文字列「January」をアイテムとしてDictionaryに追加するように,コードを書いてみた.

 キーおよびアイテムの変更
 キーの内容を変更するには,Keyメソッドにキーを引数として指定し,代入してやればよい.アイテムについても同様にItemメソッドを使えばよい.

 キーの存在を確認
 指定されたキーがあるかどうかは,Existsメソッドを使って調べることができる.下のコードでは,リストボックスの選択も変更しているので長い処理になっているが,基本的には1行で済む簡潔なものである.

 指定したキーを削除
 キーの削除は,Removeメソッドの引数に,削除するキーを指定してやればよい.

 全件削除
 全件の削除は単純にRemoveAllメソッドを実行すればよい.

 キー全体を取得して配列に
 キー全件を取得して配列に入れることができる.これは,Variant型の変数にそのままKeysプロパティを代入してやればよい.Variant配列からは,下記のコードのようにそのひとつずつを得ることができる.これは定石である.

 アイテム全体を取得して配列に
 アイテム全体についても,キーのとき同様にItemsプロパティで得ることができる.

 テキストストリームへの書き込み
 テキストストリームを使うには,OpenTextFileメソッドにファイル名や読み書きモード,上書きモード,使用する文字コード(UniCodeやASCII)などを指定する.戻り値としてTextStreamオブジェクトを得ることができる.
 このオブジェクトの読み書きは,Write, WriteLine, Read, ReadLineなどのように,文字列単位あるいは行単位ですることができる.ただし,カンマ区切りなどにするには,意図的に文字列中にカンマを入れておいてからWriteなどをする必要がある.安直にWriteしてしまうと,その内容は文字列が続けて書き込まれてしまう.当然,あとから区切りを探さないといけない.
 そこで,ここではWriteLineメソッドを使って,キーとアイテムを1行ずつ書き込んだ.途中でファイルがおかしくならない限り,これでそのまま復元できるというわけだ.また,書き込み時や読み込み時に,LineおよびColumnプロパティで,何行目の何カラムにポインタがあるかを知ることができる(リスト3・図11).

(リスト3)

図11:テキストストリームを扱うサンプル

Visual Basicの未来は明るい

 さて,WSHに含まれる各種のオブジェクトの使い方を見てきたが,いかがだっただろうか.従来はWindows APIバリバリでないと使えなかった機能が,実にカンタンに使うことができ,非常に便利である.
 実は,このような便利なオブジェクトは,Internet Explorerをインストールしたときに同時にインストールされるActiveXコントロールやオブジェクトにも,いろいろなものがある.しかし,IEはセキュリティ上問題があることから使用禁止になっている企業も多く,そういったものがあることを前提にしてプログラムを作ることには問題がある.その点,WSHであれば安心であり,今後はWindows上の標準的なオブジェクトとなっていくハズだ.
 私はこの時を待っていたのだ.「いずれは,Windows APIを使わなくても,Visual Basicからすべての処理を書くことができるようになる日が来るハズだ」と,Visual Basic 4.0が発売される前から書いてきた.一時は,そんな日は本当に来るのかと疑問に思ったこともあったが,VB5での大幅な改良やこういったオブジェクトの登場で,少しは真実味を帯びてきたようである.
 Visual BasicからWindows APIを使う意味が完全になくなる日は来ないだろうが,たいていの処理はオブジェクトを使って書くことができるようになりつつあるのは確かだ.そういう意味では,やはりVisual Basicの未来は明るいと言えるのではないだろうか.

サンプルプログラムのダウンロード


VB Magazine ライブラリ | Visual Basic WorkGroup
int21 ホームページ | PCDN ホームページ


Copyright (c) 1998 PCDN All Rights Reserved.
For questions or comments, please send mail to: pcdn@int21.co.jp