【入門編】【上級プロフェッショナル向け】大量図面のオープン・クローズに伴うGDIリソース消費の監視と強制ガベージコレクション – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!AutoCAD VBAの世界へようこそ。
日々、何百枚、何千枚という膨大な図面ファイル(DWG)のバッチ処理や図面データの集計に追われていませんか?

「最初は順調に動いていたマクロが、処理を重ねるうちに妙に遅くなり、最終的にAutoCADごとフリーズしてしまう……」
もしあなたがそんな悪夢にうなされているなら、それはあなたのコードの書き方が悪いわけではありません。AutoCADという巨大な巨人が抱える「GDIリソースとメモリの呪縛」に直面している証拠です。

今回は、プログラミング初学者から「マクロの記録」を卒業して一歩先へ進みたいあなたに向けて、数千枚の図面を完走するための【上級プロフェッショナル向け】メモリ・リソース管理の極意を、優しく、そして本質的に解説していきます。

ここをクリアすれば、あなたも立派な自動化エンジニアの仲間入りです。さあ、一緒に扉を開けましょう!

—

1. なぜ大量の図面を処理するとAutoCADは「重く」なるのか?

AutoCAD VBAで `Documents.Open` を使って図面を開き、処理が終わったら `Close` する。一見、これだけでメモリは綺麗に解放されているように思えますよね。

しかし、Windowsの裏側(APIの領域)を覗いてみると、話は全く違います。
AutoCADは内部で大量のWindowsグラフィックリソース(GDIハンドルやユーザーハンドル)やCOMオブジェクトの参照を生成しています。これらは、VBAの `Close` や `Quit` だけでは完全に回収しきれない「ゴミ(メモリリークの残骸)」を少しずつ残していきます。

  • 10枚の処理: なんともない
  • 100枚の処理: 少し動作が怪しくなる
  • 1,000枚の処理: メモリがパンクし、AutoCADが沈黙する(フリーズ・強制終了)

この現象を防ぐためには、単に図面を閉じるだけでなく、「Windowsのリソース使用量を監視し、限界が来る前にAutoCADのプロセス自体をリフレッシュ(再起動)する」という、プロならではの防衛策が必要になります。

—

2. 解決へのアプローチ:VBAとWindows APIの融合

今回は、以下の戦略でこの問題を華麗に解決します。

1. Windows API (`GetProcessMemoryInfo` など) を使って、現在のAutoCADが消費しているメモリ量をリアルタイムで監視する。
2. あらかじめ設定した「安全閾値(例: 1GBを超えたら)」を超えた瞬間を検知する。
3. 現在のインスタンスを安全にセーブ&シャットダウンし、VBAの外側(シェル等)からAutoCADを再起動して処理を継続する。

……と聞くと「難しそう!」と思うかもしれませんが、安心してください。先輩がコピペで使える実用コードを用意しました。

—

3. 実装コード:メモリ監視付き・図面一括処理エンジン

以下のコードは、指定したフォルダ内のすべてのDWGファイルを安全に巡回し、メモリ肥大化を検知した時点で自動的にプロセスをリフレッシュしながら処理を継続するメインエンジンの骨組みです。

Option Explicit

‘ — Windows APIの宣言(メモリ使用量を取得するため) —
If Win64 Then
Private Declare PtrSafe Function GetCurrentProcess Lib “kernel32” () As LongPtr
Private Declare PtrSafe Function GetProcessMemoryInfo Lib “psapi.dll” ( _
ByVal Process As LongPtr, _
ByCallback As Any, _
ByVal cb As Long) As Long

‘ 64ビット用の構造体
Private Type PROCESS_MEMORY_COUNTERS
cb As Long
PageFaultCount As Long
PeakWorkingSetSize As LongLong
WorkingSetSize As LongLong ‘ ← 現在の物理メモリ使用量
QuotaPeakPagedPoolUsage As LongLong
QuotaPagedPoolUsage As LongLong
QuotaPeakNonPagedPoolUsage As LongLong
QuotaNonPagedPoolUsage As LongLong
PagefileUsage As LongLong
PeakPagefileUsage As LongLong
End Type
Else
‘ 32ビット環境の場合は適宜型を調整しますが、現代は64bitが主流です
End If

‘ 許容するメモリの閾値(例:1.5GBを超えたらリフレッシュ)
Const MEMORY_LIMIT_MB As Long = 1500

Sub BatchProcessWithMemoryGuard()
Dim targetFolder As String
targetFolder = “C:\AutoCAD_Drawings\” ‘ 処理対象フォルダ

Dim fileName As String
fileName = Dir(targetFolder & “.dwg”)

Dim processedCount As Long
processedCount = 0

Do While fileName <> “”
‘ 1. メモリ使用量をチェック
If CheckMemoryUsage() > MEMORY_LIMIT_MB Then
Debug.Print “【警告】メモリ消費量が閾値を超過しました。AutoCADをリフレッシュします。”

‘ ※実務ではここで「未保存データの退避」や「インデックスファイルの保存」を行い、
‘ VBAから外側のバッチ(.bat)へ処理を引き継いでAutoCADを終了させます。
Exit Sub
End If

‘ 2. 図面のオープンと処理
Dim doc As AcadDocument
On Error GoTo ErrorHandler

Set doc = Documents.Open(targetFolder & fileName, ReadOnly:=True)

‘ — ここに実際の図面処理(レイヤ変更や文字置換など)を記述 —
Call DoSomething(doc)

‘ 3. 確実に図面を閉じる
doc.Close SaveChanges:=False
Set doc = Nothing

processedCount = processedCount + 1
fileName = Dir ‘ 次のファイルへ
Loop

MsgBox “全 ” & processedCount & ” 枚の処理が正常に完了しました!”, vbInformation
Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
If Not doc Is Nothing Then doc.Close SaveChanges:=False
End Sub

‘ 現在のAutoCADプロセスのメモリ使用量(MB)を取得する関数
Private Function CheckMemoryUsage() As Long
Dim pmc As PROCESS_MEMORY_COUNTERS
pmc.cb = LenB(pmc)

If GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) <> 0 Then
‘ バイト単位からMB単位へ変換
CheckMemoryUsage = CLng(pmc.WorkingSetSize / (1024 1024))
Else
CheckMemoryUsage = 0
End If
End Function

‘ ダミーの処理プロシージャ
Private Sub DoSomething(targetDoc As AcadDocument)
‘ 例:モデル空間のエンティティ数をイミディエイトウインドウに出力
Debug.Print targetDoc.Name & ” 処理中… エンティティ数: ” & targetDoc.ModelSpace.Count
End Sub

—

4. コードの解説と「陥りやすい罠」

このコードのポイントは、`CheckMemoryUsage` 関数でWindowsのAPIを叩き、現在のプロセスがどれだけのメモリ(WorkingSetSize)を専有しているかを常に監視している点です。

陥りやすい罠:「変数の解放漏れ」

VBAでよくあるミスが、`Set doc = Nothing` を書き忘れるケースです。これを行うことで、VBA側のCOM参照カウンタが減少し、ガベージコレクション(メモリ掃除)のトリガーを引くことができます。
しかし、前述の通りAutoCAD本体のGDIリソースまでは完璧に回収されません。だからこそ、「閾値を超えたらプロセスごと再起動する」という運用上の割り切り(オートメーションの設計)がプロの現場では必要不可欠なのです。

—

まとめ:ここをクリアすれば、あなたもバッチ処理マスター!

今回は、数千枚の図面処理における最大の壁「メモリ肥大化とGDIリソース枯渇」に対するアプローチをご紹介しました。

  • AutoCAD VBA単体では限界があることを知る
  • Windows APIを組み合わせてメモリを監視する
  • 限界を迎える前にプロセスをリフレッシュする仕組み(設計思想)を持つ

この3つを抑えておけば、どんなに膨大な数の図面が押し寄せてきても、もう夜中にAutoCADがフリーズして朝絶望するようなことはありません。

「ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ!」
ぜひ、あなたの現場の自動化ツールにこの知見を取り入れ、圧倒的な作業効率を手に入れてください。それでは、次回の技術コラムでお会いしましょう!

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