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

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

単一スレッドの限界を突破せよ:VBScriptを用いたAutoCAD並列変換アーキテクチャの極意

AutoCADの自動化に取り組むエンジニアが必ず直面する、逃れられない「壁」がある。それは、VBA(Visual Basic for Applications)がシングルスレッド・モデルであるという事実だ。

大量のDWGファイルを、旧バージョン(例:2013形式)から新バージョン(例:2018形式)へ、あるいはその逆へと一括変換する業務を想像してほしい。1ファイルに10秒かかる処理を、1,000ファイルに対して直列(シーケンシャル)に実行すれば、それだけで約2.7時間。業務時間の大半を、ただプログレスバーを眺めるだけの無益な時間に費やすことになる。

「VBAでループを回せばいい」――そんな思考停止した設計は、プロフェッショナルの仕事ではない。我々が目指すべきは、「複数のAutoCADインスタンスを並列に制御し、マシンのリソースを限界まで使い切る並列処理アーキテクチャ」の構築である。

本稿では、VBAの限界を外部から突破するための、VBScriptを用いたオーケストレーション手法を詳解する。

1. アーキテクチャ設計:なぜVBScriptなのか?

VBA単体では、自身のプロセス内で新しいスレッドを生成することは不可能だ。そこで、AutoCADの外側に「指揮官(Orchestrator)」を配置する必要がある。

ここでVBScriptを選択する理由は、その軽量性とCOM(Component Object Model)への親和性にある。PythonやC#も有力な候補だが、追加のランタイムインストールが制限される企業の業務環境において、Windows標準のVBScriptは、最も「堅牢かつポータブルな解決策」となる。

設計コンセプト:Orchestrator-Workerパターン

1. Orchestrator (VBScript): タスクリスト(変換対象ファイル一覧)を読み込み、利用可能なCPUリソースに基づき、複数のAutoCADインスタンス(Worker)を起動・管理する。
2. Worker (AutoCAD Instance): 各インスタンスは独立したメモリ空間を持ち、与えられた単一のタスク(ファイルのオープン $\to$ バージョン変換 $\to$ 保存 $\to$ 終了)を完結させる。
3. Task Queue (CSV/Database): どのファイルが処理済みで、どれが未処理かを管理し、プロセスの中断・再開を可能にする。

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

以下に、複数のAutoCADインスタンスを立ち上げ、並列で図面変換を実行するためのプロダクションレベルのコード例を示す。ここでは、並列数を制御する「スロット制」の概念を導入している。

' ==============================================================================
' AutoCAD Parallel Conversion Engine (VBScript)
' 
' 【概要】
' 複数のAutoCADインスタンスを並列に制御し、DWGのバージョン変換を高速化する。
' 【注意】
' 実行前に、変換対象のファイルリスト(task_list.csv)を用意すること。
' ==============================================================================

Option Explicit

' --- 定数定義 (AutoCADの定数はVBScriptでは参照できないため、手動定義が必要) ---
Const ACDB_OPEN = 0
Const AC_R2013 = 1  ' AutoCAD 2013形式
' ※環境に合わせて適切な定数を定義すること

' --- 設定パラメータ ---
Dim MAX_PARALLEL_INSTANCES : MAX_PARALLEL_INSTANCES = 3 ' 同時起動数(CPU/RAMに応じて調整)
Dim TASK_LIST_PATH          : TASK_LIST_PATH = "C:\Automation\task_list.csv"
Dim LOG_FILE_PATH           : LOG_FILE_PATH = "C:\Automation\process.log"

' --- グローバル管理変数 ---
Dim objFSO, objTaskFile
Dim arrTasks() ' タスク配列
Dim taskCount : taskCount = 0

Set objFSO = CreateObject("Scripting.FileSystemObject")

Sub Main()
    LoadTasks
    If taskCount = 0 Then
        WScript.Echo "タスクが見つかりません。"
        Exit Sub
    End If

    WScript.Echo "処理を開始します。並列数: " & MAX_PARALLEL_INSTANCES

    Dim activeInstances : activeInstances = 0
    Dim currentTaskIdx : currentTaskIdx = 0
    Dim runningWorkers : Set runningWorkers = CreateObject("Scripting.Dictionary")

    ' メインループ:全タスクが完了するまで回す
    Do While currentTaskIdx < taskCount Or runningWorkers.Count > 0
        
        ' 1. 空きスロットがあれば新しいWorkerを起動
        Do While runningWorkers.Count < MAX_PARALLEL_INSTANCES And currentTaskIdx < taskCount
            Dim taskPath : taskPath = arrTasks(currentTaskIdx)
            Dim acadApp : Set acadApp = StartAutoCAD()
            
            If Not acadApp Is Nothing Then
                ' 非同期的に処理を開始させるため、ここではインスタンスを保持
                ' 注:VBScript単体での完全な非同期制御は難しいため、
                ' 本来は各Workerを別プロセス(WScript.Run)として切り出すのが理想。
                ' ここでは概念を示すため、逐次処理の拡張として記述。
                
                ' ※実務では、WScript.Run を用いて「別プロセスとしてVBScriptを起動」し、
                ' 戻り値を待たない設計にすることで真の並列化を実現する。
                ProcessTask acadApp, taskPath
                runningWorkers.Add currentTaskIdx, acadApp
                currentTaskIdx = currentTaskIdx + 1
            Else
                WScript.Echo "AutoCADの起動に失敗しました。"
                Exit Do
            End If
        Loop

        ' 2. 完了したWorkerのクリーンアップ (簡易的な実装)
        ' 実際の実装では、プロセスIDや終了イベントを監視する
        ' (ここでは簡略化のため、直列的な挙動をベースとした構造を示している)
        
        ' ※究極の並列化には、以下のように「タスクを引数に持つ別スクリプト」を
        ' WScript.Run で複数起動する手法が最も堅牢である。
    Loop

    WScript.Echo "すべての処理が完了しました。"
End Sub

' --- AutoCADインスタンスの起動 ---
Function StartAutoCAD()
    On Error Resume Next
    Dim acadApp
    Set acadApp = CreateObject("AutoCAD.Application")
    If Err.Number <> 0 Then
        Set StartAutoCAD = Nothing
    Else
        acadApp.Visible = True ' デバッグ時はTrue、本番はFalseを推奨
        Set StartAutoCAD = acadApp
    End If
    On Error GoTo 0
End Function

' --- 図面変換のコアロジック ---
Sub ProcessTask(acadApp, filePath)
    On Error Resume Next
    Dim doc, savePath
    savePath = objFSO.GetParentFolderName(filePath) & "\" & _
               objFSO.GetBaseName(filePath) & "_converted.dwg"

    Set doc = acadApp.Documents.Open(filePath)
    
    If Err.Number = 0 Then
        ' SaveAs(ファイル名, バージョン)
        doc.SaveAs savePath, AC_R2013
        doc.Close False
        WriteLog "SUCCESS: " & filePath
    Else
        WriteLog "ERROR: " & filePath & " (Error: " & Err.Description & ")"
        doc.Close False
    End If
    
    ' メモリ解放
    Set doc = Nothing
    On Error GoTo 0
End Sub

' --- ユーティリティ関数 ---
Sub LoadTasks()
    ' CSVからファイルパスを読み込む実装 (省略)
End Sub

Sub WriteLog(msg)
    Dim ts : Set ts = objFSO.OpenTextFile(LOG_FILE_PATH, 8, True)
    ts.WriteLine Now & " : " & msg
    ts.Close
End Sub

Main

3. プロフェッショナルのための「設計の急所」

上記のコードは概念を示すためのものだが、実務で「使い物になる」ツールにするためには、以下の3点を極限まで突き詰める必要がある。

① 真の並列化:`WScript.Run` によるプロセスの分離

上記のコードをそのまま実行すると、VBScriptの性質上、一つのループ内で順次実行されてしまう。真の並列化を実現するには、「Orchestrator」が「Worker(別のVBScript)」を `WScript.Run` で引数付きで叩く設計にせよ。

' Orchestrator内での実行イメージ
WScript.Run "wscript.exe ""C:\Scripts\Worker.vbs"" """ & targetFilePath & """", 0, False

`False` を指定することで、Workerの終了を待たずに次のプロセスを起動できる。これが「マルチスレッド的アプローチ」の正体だ。

② リソース・ガバナンス(メモリとCPUの衝突)

AutoCADは非常に重いアプリケーションだ。並列数を増やしすぎると、以下の現象が発生し、システム全体がクラッシュする。

  • RAMの枯渇: 1インスタンスあたり2GB消費すると仮定し、32GBのメモリでは最大12〜14プロセスが限界だ。
  • レジストリ・競合: 同時に複数のAutoCADが起動すると、ユーザー設定の読み込みで競合が発生することがある。
  • 対策: `MAX_PARALLEL_INSTANCES` は、計算式(`LogicalProcessors * 0.5` など)に基づき、余裕を持って設定すること。

③ ゾンビプロセスの根絶

自動化ツールにおいて最も恐ろしいのは、エラー発生時にAutoCADのプロセスだけがメモリ上に残り続ける「ゾンビプロセス」だ。

  • 対策: Workerスクリプトの最後には必ず `Set acadApp = Nothing` を行い、さらにOrchestrator側で、一定時間内に終了しなかったプロセスを `taskkill` 等で強制終了する監視ロジックを組み込むこと。

4. 結論

AutoCAD VBAの単一スレッドという制約は、設計の力によって容易に打破できる。

単に「コードを書く」のではなく、「複数のプロセスをいかに調和させ、リソースを管理するか」というシステムエンジニアリングの視点を持つこと。これこそが、凡庸な自動化担当者と、伝説的なチーフアーキテクトを分かつ境界線である。

次なるステップとして、このアーキテクチャに「DB連携による進捗管理」や「エラー発生時の自動リトライ機能」を実装し、真にプロフェッショナルなプロダクションツールへと昇華させてほしい。

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