【テクニカル・上級編】【上級プロフェッショナル向け】マルチスレッド的アプローチ:VBScriptから複数のAutoCADインスタンスを制御し、図面変換を並列処理する – AutoCAD VBA解析バイブル

スポンサーリンク
スポンサーリンク

【極限の知見】VBAの限界を突破せよ:マルチインスタンス制御によるAutoCAD図面変換の並列化アーキテクチャ

AutoCAD VBAという領域に足を踏み入れたエンジニアが、必ずと言っていいほど直面する「壁」がある。それは、VBAが本質的にシングルスレッドであるという事実だ。

数千、数万という図面ファイルを、特定のバージョン(例:2018形式から2013形式)へ一括変換するタスクを想像してほしい。標準的なVBAマクロで実装すれば、それは「一本の細い道を、一台の車がひたすら走り続ける」ようなものだ。処理が終わるのを待つ間、CPUのマルチコアは遊休状態となり、時間は無慈悲に過ぎ去る。

シニアエンジニアとして、我々が取るべき道は「コードの書き換え」ではない。「実行アーキテクチャの再構築」だ。

本稿では、VBAのシングルスレッド制限を外部から打破し、複数の`AcadApplication`インスタンスを並列制御することで、図面変換処理を極限まで加速させる「マルチインスタンス・オーケストレーション」の真髄を解き明かす。

1. アーキテクチャの転換:Worker-Orchestratorモデル

単一のVBAプロジェクト内で並列処理を行おうとするのは、設計思想として誤りだ。AutoCADのCOMオブジェクトモデルは、プロセスレベルでの分離を前提とした制御が最も安定する。

我々が構築すべきは、以下の二層構造である。

1. Worker (実行体): 単一のAutoCADインスタンスを受け取り、特定の図面を変換して終了する「無心な作業員」。これはVBA、あるいはVBScriptで記述される。
2. Orchestrator (指揮者): 複数のWorkerをプロセスとして起動・管理し、リソース(CPU/メモリ/ライセンス)の閾値を超えないように制御する「司令塔」。これはVBScriptやPowerShell、あるいはC#によって実装される。

これにより、VBAの限界であった「一つのプロセスに縛られる制約」を、OSレベルのプロセス並列へと昇華させる。

2. 実装:並列変換エンジン

ここでは、VBScriptをOrchestratorとして使い、複数のAutoCADプロセスを立ち上げて並列処理を行うプロトタイプを示す。

2.1 Worker層:図面変換のコアロジック (VBScript/VBA)

まず、単一のファイルを受け取り、変換して閉じる最小単位のロジックを定義する。ここでは、外部から引数としてファイルパスを受け取れるように構成する。

' File: DWGConverter_Worker.vbs
' 役割: 単一のDWGファイルを指定のバージョンへ変換して終了する

Option Explicit

Dim objArgs, targetFile, saveAsPath, acadApp, doc

' コマンドライン引数の取得
Set objArgs = WScript.Arguments
If objArgs.Count < 2 Then
    WScript.Echo "Usage: DWGConverter_Worker.vbs [SourceFile] [DestFile]"
    WScript.Quit 1
End If

targetFile = objArgs(0)
saveAsPath = objArgs(1)

On Error Resume Next

' AutoCADインスタンスの生成(新しく起動する)
Set acadApp = CreateObject("AutoCAD.Application")

If Err.Number <> 0 Then
    WScript.Echo "Error: AutoCADの起動に失敗しました。"
    WScript.Quit 1
End If

' 非表示モードでの実行(パフォーマンスと安定性のための定石)
' ※ただし、デバッグ時は True にして挙動を確認すべきである
acadApp.Visible = False 

' 図面のオープン
Set doc = acadApp.Documents.Open(targetFile)

If Err.Number <> 0 Then
    WScript.Echo "Error: 図面を開けません: " & targetFile
    acadApp.Quit
    WScript.Quit 1
End If

' --- バージョン変換の核心 ---
' SaveAsメソッドの引数はAutoCADのバージョンに依存する。
' ここでは例として、定数を用いて保存を行う。
' ※実際の開発では、AutoCADのバージョンに応じた定数定義が必要。
doc.SaveAs saveAsPath 

' 終了処理:オブジェクトの明示的な解放
doc.Close False
Set doc = Nothing

' AutoCADアプリケーションの終了
acadApp.Quit
Set acadApp = Nothing

If Err.Number <> 0 Then
    WScript.Echo "Error during conversion: " & Err.Description
    WScript.Quit 1
Else
    WScript.Quit 0
End If

2.2 Orchestrator層:プロセス管理 (VBScript)

次に、上記のWorkerを並列で走らせる司令塔だ。ここでは、同時に起動するプロセス数(Concurrency)を制御し、システムリソースの枯渇を防ぐ。

' File: DWGConverter_Orchestrator.vbs
' 役割: 複数のWorkerプロセスを管理し、並列実行する

Option Explicit

Dim shell, fso, workerScript, sourceDir, destDir, files, file, i
Dim maxParallel, currentRunning, cmd

' --- 設定領域 ---
workerScript = "C:\Scripts\DWGConverter_Worker.vbs" ' Workerのパス
sourceDir = "C:\Input\DWG\"
destDir = "C:\Output\DWG\"
maxParallel = 3 ' 同時実行プロセス数(CPUコア数とメモリ量に応じて調整)
' ----------------

Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")

' 入力ディレクトリのファイルリスト取得
Set files = fso.GetFolder(sourceDir).Files

' 本来はここでキュー(Queue)を構築するが、
' 簡略化のため、逐次的にプロセスを管理するロジックを示す
' ※実戦では、WshShell.Run の戻り値やプロセス監視を組み込む

WScript.Echo "Parallel Conversion Started..."

' 簡易的な並列制御ロジック(概念実証)
' 実際には、各プロセスのPIDを監視し、終了を確認しながら次を投入する
' ここでは、実装の複雑さを避けるため、概念的なフローを示す

' 1. ファイルリストを配列に格納
' 2. ループ内で、maxParallel数までプロセスを起動
' 3. 終了したプロセスを検知し、次のファイルを投入

' [注釈] プロフェッショナルな実装では、WMI (Windows Management Instrumentation) 
' を使用して、特定のプロセス(acad.exe)が残っていないかを監視するのが鉄則である。

WScript.Echo "Orchestration logic initialized. Implement WMI monitoring for production."

3. 伝説のアーキテクトが教える「極限の知見」

このアーキテクチャを実戦投入する際、凡庸なエンジニアが見落とし、システムを崩壊させる「3つの落とし穴」がある。

① COMオブジェクトの「ゴースト・プロセス」問題

`Set obj = Nothing` を書いたからといって、`acad.exe` が終了するとは限らない。特にエラー発生時にオブジェクト参照が残ると、メモリ上に「ゾンビ化したAutoCAD」が蓄積し、数時間後にはサーバーのメモリを食いつぶし、OSごとフリーズさせる。

  • 対策: Workerの最後に必ず `On Error` で捕捉し、エラー時でも `acadApp.Quit` を確実に実行すること。また、Orchestrator側で WMI (Windows Management Instrumentation) を使い、一定時間経過しても終了していない `acad.exe` を強制終了(`TerminateProcess`)する「クリーンアップ・デーモン」を実装せよ。

② ライセンス・コンテンション(競合)

AutoCADを並列で起動するということは、その数だけライセンス・シートを消費することを意味する。ネットワークライセンス(Multi-user)環境において、`maxParallel` をライセンス数以上に設定した瞬間、プロセスは「ライセンス取得待ち」でデッドロックに陥る。

  • 対策: ライセンスの在庫数と、メモリ(1インスタンスあたり数GBを消費する)の閾値を計算し、数学的に導き出された「最適並列数」を `maxParallel` に設定せよ。

③ I/O バウンドとCPUバウンドの境界線

図面変換は、CPU計算(ジオメトリの再計算)と、ディスクI/O(ファイルの読み書き)の両方に負荷がかかる。並列数を増やしすぎると、ディスクのヘッド(またはSSDのコントローラ)がボトルネックとなり、逆にスループットが低下する。

  • 対策: NVMe SSDを使用している環境であれば、CPUコア数に寄せた高並列化が有効だ。一方で、ネットワークドライブ上のファイルを操作する場合、並列数を絞り、I/O待ちによるタイムアウトを防ぐ設計にせよ。

結論

VBAは、単体では確かに脆弱なシングルスレッドのツールだ。しかし、Windows APIやWMI、そしてプロセス間通信という「外部の力」を借りることで、その限界は容易に突破できる。

真の自動化エンジニアとは、言語の仕様に縛られる者ではない。OSの挙動を理解し、リソースを支配し、システム全体を俯瞰して最適なアーキテクチャを設計できる者を指すのだ。

この「マルチインスタンス・オーケストレーション」をマスターした時、君の自動化技術は、単なる「マクロ」から「エンタープライズ・ソリューション」へと昇華するだろう。

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