【入門編】【特定COMオブジェクトの生存チェック】CreateObject失敗時のレジストリ自動確認とCOMコンポーネント再登録バッチ – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

やあ、業務自動化の世界へようこそ!頼れる先輩エンジニアの私と一緒に、VBScriptの真の力を解き放つ旅に出かけましょう。

「Excelマクロの記録から抜け出して、もっと本格的なWindows自動化をしたい!」
「作ったスクリプトを別のPCで動かしたら `ActiveX コンポーネントを作成できません (エラー 429)` と怒られた…」

こんな経験はありませんか?焦らなくて大丈夫ですよ。VBScriptを扱い始めたエンジニアが必ず通る「登竜門」が、このCOMオブジェクトの生成とライフサイクル管理です。

今回は、エラーが起きたらスクリプト自身がレジストリを確認し、未登録のDLL/OCXファイルを自動で再登録(`regsvr32`)して復活する、「自己修復型(Self-Healing)VBScript」の構築手法を伝授します。ここをマスターすれば、VBScriptの基礎とWindows内部の仕組みはバッチリですよ!

1. COMとレジストリの仕組みを「図解」で捉えよう

まずは、VBScriptが `CreateObject` を実行したとき、Windowsの裏側で何が起きているのかを視覚的に理解しましょう。

`CreateObject` 実行時の裏側

【VBScript】 CreateObject(“Vendor.CustomComponent”)


【Windowsレジストリ】 HKEY_CLASSES_ROOT\Vendor.CustomComponent
│ (ProgIDから「CLSID」と呼ばれる一意のIDを検索)

【Windowsレジストリ】 HKEY_CLASSES_ROOT\CLSID\{XXXX-XXXX-…}\InprocServer32
│ (実体となるDLL/OCXファイルのパスを取得)

【ファイルシステム】 C:\Program Files\Common Files\Vendor\Component.dll
│ (メモリ上にロードしてオブジェクト生成)

【実行完了】 オブジェクト利用可能!

普段私たちが指定している `”Vendor.CustomComponent”` のような文字列は「ProgID(プログラムID)」と呼ばれます。Windowsはこれをキーにしてレジストリを検索し、実際のファイル(DLLやOCX)を見つけ出しているのです。

ファイルが存在しない、あるいはレジストリの登録が消えていると、`CreateObject` は失敗します。そこで今回は、以下のような「自己修復ループ」を組み込みます。

[CreateObject 実行]

├─► 成功 ──► 通常の業務処理へ

└─► 失敗 (エラー発生)


[レジストリ自動チェック]

├─► 未登録/異常を検知
│ │
│ ▼
│ [regsvr32 を無音実行して再登録]
│ │
│ ▼
└─► [CreateObject 再実行 (復旧)]

2. 実践!自己修復型VBScriptの完全コード

それでは、現場でそのままコピペして使える完全なコードを紹介します。まずはコードの全体像を確認し、そのあとでポイントを一つずつ紐解いていきましょう。

‘===============================================================================
‘ 【自己修復型 COMオブジェクト生存チェック&自動再登録スクリプト】

‘ 概要: 目的のCOMオブジェクト生成を試み、失敗した場合はレジストリを確認。
‘ 未登録であれば regsvr32 を自動実行して再登録を試みます。
‘===============================================================================
Option Explicit

‘ — 設定エリア —
Const TARGET_PROGID = “Vendor.CustomComponent” ‘ 生成したいProgID
Const DLL_FILE_PATH = “C:\Windows\System32\VendorComp.dll” ‘ 対象のDLL/OCX絶対パス

‘ — メイン処理 —
Dim myObject
Set myObject = SafeCreateObject(TARGET_PROGID, DLL_FILE_PATH)

If Not myObject Is Nothing Then
WScript.Echo “【成功】オブジェクトの生成に成功しました!業務処理を開始します。”

‘—————————————————————————
‘ ここに本来行いたい業務ロジックを記述します
‘—————————————————————————

‘ メモリの明示的解放(VBScriptエンジニアの嗜み)
Set myObject = Nothing
Else
WScript.Echo “【致命的エラー】コンポーネントの自動修復に失敗しました。管理者へ連絡してください。”
End If

‘===============================================================================
‘ 関数名: SafeCreateObject
‘ 概要 : エラーハンドリングと自動修復機能を備えた CreateObject ラッパー
‘ 引数 : strProgID (String) – 生成するオブジェクトのProgID
‘ strDllPath (String) – 再登録に使用するDLLの絶対パス
‘ 戻り値: Object (成功時) / Nothing (失敗時)
‘===============================================================================
Function SafeCreateObject(ByVal strProgID, ByVal strDllPath)
Dim objShell, objTarget
Dim regPath, regValue

‘ エラーが発生してもスクリプトを停止させず、自力で処理する宣言
On Error Resume Next

‘ 1回目のオブジェクト生成試行
Set objTarget = CreateObject(strProgID)

‘ エラーがなければそのままオブジェクトを返却
If Err.Number = 0 Then
Set SafeCreateObject = objTarget
On Error GoTo 0 ‘ エラー通知を通常状態に戻す
Exit Function
End If

‘ — エラー検知:修復プロセスへ移行 —
WScript.Echo “警告: オブジェクト (” & strProgID & “) の生成に失敗。修復を実行します…”
Err.Clear ‘ エラー情報をクリア

‘ シェルオブジェクトの生成(レジストリ操作およびコマンド実行用)
Set objShell = CreateObject(“WScript.Shell”)

‘ 2. レジストリの存在確認
‘ HKCR\\CLSID のパスをチェック
regPath = “HKCR\” & strProgID & “\CLSID\”
regValue = objShell.RegRead(regPath)

If Err.Number <> 0 Then
WScript.Echo ” -> レジストリ未登録を検知しました。再登録を行います。”
Err.Clear

‘ 3. regsvr32 を使ってDLLをサイレント登録 (/s オプション)
‘ ※実行には管理者権限が必要です
Dim exitCode
exitCode = objShell.Run(“regsvr32.exe /s “”” & strDllPath & “”””, 0, True)

If exitCode <> 0 Then
WScript.Echo ” -> エラー: regsvr32 の実行に失敗しました。コード: ” & exitCode
Set SafeCreateObject = Nothing
Set objShell = Nothing
On Error GoTo 0
Exit Function
End If

WScript.Echo ” -> レジストリ再登録コマンドが完了しました。”
Else
WScript.Echo ” -> レジストリ情報は存在しますが、読み込みに失敗しています。”
End If

‘ 4. 再登録後のリトライ(最後の生成試行)
Set objTarget = CreateObject(strProgID)

If Err.Number = 0 Then
WScript.Echo ” -> 【修復成功】再生成に成功しました!”
Set SafeCreateObject = objTarget
Else
WScript.Echo ” -> 【修復失敗】エラーコード: ” & Err.Number & ” – ” & Err.Description
Set SafeCreateObject = Nothing
End If

‘ 後片付け
Set objShell = Nothing
On Error GoTo 0 ‘ エラー制御をデフォルトに戻す
End Function

3. 初学者が陥りやすい「3つの罠」と解説

このコードには、一流のVBScriptエンジニアになるための重要なテクニックが凝縮されています。陥りやすいポイントと合わせて見ていきましょう!

① `On Error Resume Next` の使いどころと解除

VBScriptには一般的なプログラミング言語のような `Try…Catch` 構文がありません。代わりに `On Error Resume Next` を使います。
これは「エラーが起きても無視して次の行に進め!」という強力な命令です。使いっぱなしにすると、他の場所で致命的なバグが起きても気づけなくなります。
目的の処理が終わったら、必ず `On Error GoTo 0` を呼び出して、通常のエラー検知状態に戻すのがプロの鉄則です。

② レジストリ検索 (`RegRead`) の仕組み

`WScript.Shell` の `RegRead` メソッドは、指定したキーや値が存在しない場合に例外エラーを発生させます。今回はあえてその挙動を利用し、`Err.Number <> 0` になるかどうかで「レジストリに登録されていない」という状態を判別しています。

③ 32bit / 64bit の壁 (SysWOW64の落とし穴)

ここが最もハマりやすいポイントです!
64bit版のWindowsでは、COMオブジェクトも「32bit用」と「64bit用」で格納場所が異なります。

  • 64bitオブジェクト: `C:\Windows\System32\regsvr32.exe` で登録
  • 32bitオブジェクト: `C:\Windows\SysWOW64\regsvr32.exe` で登録

もし古い32bitのOCX/DLLファイルを扱う場合は、スクリプトを `C:\Windows\SysWOW64\wscript.exe` から実行するか、`regsvr32` の呼び出しパスを `SysWOW64` 側に明示的に書き換える必要があります。

4. ライフサイクル管理(後片付け)の美学

コードの最後にある `Set myObject = Nothing` や `Set objShell = Nothing`。
「スクリプトが終われば勝手に消えるんじゃないの?」と思うかもしれません。半分正解ですが、エンジニアとしては不合格です。

VBScript(WSH環境)は、参照されなくなったオブジェクトのメモリを解放する「参照カウント」方式を採用しています。明示的に `Nothing` を代入することで、Windows OSに対して即座に「このメモリはもう使わないから開放していいよ!」と通知できます。

特にループ処理の中で `CreateObject` を繰り返す場合、後片付けを怠るとメモリリークを引き起こし、パソコン全体の動作が重くなってしまいます。「生成したら、最後は Nothing で閉じる」。これを習慣にしましょう!

まとめ:ここをクリアすればVBScriptの基本はバッチリ!

今回は、単に `CreateObject` を使うだけでなく、以下の「一歩進んだ技術」を学びました。

1. エラーハンドリングの制御 (`On Error Resume Next` と `GoTo 0`)
2. `WScript.Shell` を使ったレジストリの読み込みと外部コマンド実行
3. `regsvr32` によるコンポーネントの自己修復
4. 適切なオブジェクト解放 (`Set = Nothing`)

これが理解できれば、あなたの書くスクリプトの堅牢性(壊れにくさ)は格段に跳ね上がります。他の人が「動かない!」と頭を抱えている横で、あなたのスクリプトは自力で修復して何事もなかったかのように動いている……カッコいいですよね!

焦らず一歩ずつ進んでいきましょう。疑問があればいつでも聞いてくださいね。応援しています!

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