【入門編】【COMコンポーネント依存性チェック】 CreateObject 実行前のレジストリ (HKCR) 事前確認による安全なエラー未然防止 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
業務自動化やキッティングの現場で、VBScriptは今でもいぶし銀の輝きを放つ強力なツールです。「WSH(Windows Script Host)」の軽快さと、OSの奥深くまで触れることができるその力は、正しく使えば最強の相棒になります。

さて、現場でVBScriptを書いていると、こんな恐怖の瞬間に出会ったことはありませんか?

> 「あれ? 開発環境では動いたのに、別部署のクリーンなPCで実行したら『コンポーネントを作成できません: ‘ADODB.Stream’』ってエラーが出て強制終了した……」

……冷や汗が流れますよね。
今日は、そんな現場の事故を未然に防ぎ、「CreateObjectを実行する前に、そのCOMコンポーネントが本当に存在するかレジストリをこっそり覗き見して安全に身をかわす」という、ちょっとプロっぽい知見を伝授します。

ここをクリアすれば、あなたの書くスクリプトは一段と「プロの仕事」に近づきますよ。さあ、一緒に扉を開けましょう!

1. なぜ `CreateObject` は突然牙をむくのか?

VBScriptで外部の機能(ファイル操作やXML解析など)を使うとき、私たちは当たり前のようにこんなコードを書きます。

‘ ADODB.Stream を使ってUTF-8のテキストを書き出すぞー
Set stream = CreateObject(“ADODB.Stream”)

この `CreateObject` という魔法の呪文は、Windowsの心臓部であるレジストリに問い合わせに行きます。「ねえ、『ADODB.Stream』っていう名前のプログラム(ProgID)の設計図、どこにある?」と。

もし、そのPCにOfficeが入っていなかったり、セキュリティポリシーで特定のコンポーネントが無効化されていたりすると、レジストリには「そんなもの知らん!」と冷たくあしらわれます。結果、VBScriptは「エラー 428: オブジェクトを作成できません」という残酷なメッセージを残して、無慈悲にクラッシュしてしまうのです。

従来の「やっつけ対応」の罠

初学者のうちは、「エラーが出たら無視しちゃえ!」と `On Error Resume Next` を使いがちです。

On Error Resume Next
Set stream = CreateObject(“ADODB.Stream”)
If Err.Number <> 0 Then
‘ エラー処理
End If
On Error Goto 0

これ、一見動くように見えますが、パフォーマンス的にも設計思想としても褒められたものではありません。 存在しないオブジェクトの生成を試みるという「失敗する確率の高い処理」をあえてOSに投げつけるのは、エンジニアの美学に反します。

もっとスマートに、「戦う前に、敵がそこにいるかどうかを偵察する」方法をとりましょう。

2. 秘密の裏口:レジストリの `HKCR` を直撃せよ!

実は、Windowsのレジストリには、インストールされている全てのProgID(COMコンポーネントの名前)が `HKEY_CLASSES_ROOT` (略して `HKCR`)という巨大な電話帳のように登録されています。

VBScriptからWMI(Windows Management Instrumentation)やWScript.Shellを借りることで、この電話帳をこっそり開き、「お目当てのコンポーネントの名前が載っているか?」を事前にチェックできるのです。

概念図:事前チェックの流れ

[ VBScript 実行 ]

▼ (まだ CreateObject はしない!)
[ レジストリ (HKCR) を検索 ]

├── 見つかった! ──> 安心して CreateObject へ Go!

└── 見つからない ─> 「このPCには環境がありません」と優しく警告して終了

このアプローチを取れば、無駄なエラーを発生させずに、安全に代替処理へ分岐させることができます。

3. 実践!安全すぎるCOM依存性チェック・スクリプト

それでは、実際に現場でそのままコピペして使える、極限まで堅牢性を高めたサンプルコードを公開します。今回は代表的な `ADODB.Stream` を例に取ります。

‘ ==============================================================================
‘ スクリプト名: SafeComChecker.vbs
‘ 概要: レジストリを事前確認し、COMコンポーネントの存在確認を行ってから安全に実行する
‘ ==============================================================================

Option Explicit

Dim targetProgId
targetProgId = “ADODB.Stream” ‘ チェックしたいProgID

WScript.Echo “=== COMコンポーネント依存性チェック開始 ===”

‘ 1. 事前チェックを実行
If CheckProgIdExists(targetProgId) Then
WScript.Echo “[” & targetProgId & “] は存在します。安全に処理を続行します。”

‘ ここで初めて安心してオブジェクトを生成する
Dim objStream
Set objStream = CreateObject(targetProgId)

‘ — 本来の処理をここに記述 —
objStream.Type = 2 ‘ text
objStream.Charset = “UTF-8”
‘ —————————-

Set objStream = Nothing
WScript.Echo “処理が正常に完了しました。”

-Else
‘ 存在しない場合のフォールバック(代替処理やユーザーへの通知)
WScript.Echo “【警告】[” & targetProgId & “] がこのシステムに登録されていません。”
WScript.Echo “代替の処理を実行するか、管理者に連絡してください。”
End If

WScript.Echo “=== スクリプト終了 ===”

‘ ——————————————————————————
‘ 関数名: CheckProgIdExists
‘ 引数: progId (String) – チェックしたいProgID
‘ 戻り値: Boolean – 存在する場合は True、しない場合は False
‘ ——————————————————————————
Function CheckProgIdExists(ByVal progId)
Dim shell, regPath, objTest

‘ レジストリパスの構築 (HKCR\ProgID)
regPath = “HKCR\” & progId & “\”

Set shell = CreateObject(“WScript.Shell”)

‘ WScript.Shell の RegRead メソッドは、キーが存在しない場合にエラーを返す
‘ ここだけは例外的に On Error を使うが、関数内にスコープを限定する
On Error Resume Next
shell.RegRead regPath

If Err.Number = 0 Then
CheckProgIdExists = True
Else
CheckProgIdExists = False
End If

On Error GoTo 0
Set shell = Nothing
End Function

4. コードの深掘り:ここがエンジニアのこだわりポイント

このコードには、ただ動くだけではない「プロの知見」がいくつか隠されています。

1. スコープの分離
エラーをトラップする `On Error Resume Next` は、副作用が大きいためスクリプト全体に蔓延させるとバグの温床になります。ここでは `CheckProgIdExists` という小さな関数の中に閉じ込めることで、メインの処理への悪影響を完全にシャットアウトしています。
2. `WScript.Shell` の `RegRead` の活用
レジストリのキーが存在するかどうかを調べる最も手軽で確実な方法が、WSH標準の `RegRead` です。指定したパスが存在しない場合、キレイにエラー番号を返してくれるため、それを判定材料にしています。

おわりに:VBScriptを「使い捨てもので終わらせない」ために

マクロの記録や、その場しのぎのコードから一歩抜け出すために大切なのは、「想定外の環境」に対してどれだけ優しく、かつ強靭であるかという視点です。

「動くからいいや」ではなく、「なぜ動くのか」「動かない環境ではどう振る舞うべきか」を考えたコードは、巡り巡ってあなた自身の作業時間を守ってくれる最高の盾になります。

ここをクリアしたあなたなら、もうVBScriptの基礎はバッチリです!
明日の業務自動化ライフを、より安全でスマートなものにしてくださいね。それではまた!

タイトルとURLをコピーしました