【入門編】【上級】AcadApplicationのCOM参照を完全に解放し、タスクマネージャにAutoCADを残さない終了処理 – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!AutoCADの自動化を進める中で、こんな恐怖体験をしたことはありませんか?

「VBAのマクロを実行し終わって、ExcelもAutoCADも閉じたはずなのに……タスクマネージャを開いてみたら、『acad.exe』がしぶとく居残っている!

画面には何も映っていないのに、裏側でこっそりメモリを食らい続けるこの亡霊、通称「ゾンビプロセス」。放置するとPCが重くなるだけでなく、ファイルをロックしてしまったり、次にマクロを動かしたときに「自動化エラー」を引き起こしたりする厄介な代物です。

今回は、なぜこのゾンビが生まれてしまうのか、そのメカニズムと、完全に成仏(解放)させるための極意を優しく、そしてディープに解説していきます。ここをクリアすれば、あなたもAutoCAD VBAの裏側を完全に掌握したと言えますよ!

1. なぜ「ゾンビ(acad.exe)」が生まれるのか?

まずは敵を知ることから始めましょう。
VBAから外部のアプリケーション(AutoCADなど)を操作するとき、私たちはCOM(Component Object Model)という技術を使っています。

VBAのコード内で `CreateObject` や `GetObject` を使った瞬間、裏側でAutoCADのエンジン(`AcadApplication`)が起動し、メモリ上に「参照カウンタ」というものが生成されます。

‘ AutoCADを起動してオブジェクトを取得
Dim acadApp As Object
Set acadApp = CreateObject(“AutoCAD.Application”)

この時、Windowsのメモリ上では以下のような関係が成り立っています。

  • VBA(クライアント) ──「お、AutoCADさん使ってるよ!」(参照カウント:1)
  • AutoCAD(サーバー) ──「呼ばれたから起きてるよ!」

問題は、マクロの処理が終わったときです。
「じゃあ閉じるか!」と適当にコードを書いたり、変数をそのまま放置したりすると、VBA側は「もういらないや」となっているのに、AutoCAD側との繋がり(COM参照)がメモリのどこかにプツンと切れずに残り続けることがあります。

この「お互いの認識のズレ」こそが、タスクマネージャにacad.exeを残し続ける原因なのです。

2. ありがちな「やってはいけない」終了パターン

まずは、初学者がやりがちな「ゾンビ製造マクロ」の例を見てみましょう。どこがダメか分かりますか?

Sub BadExample()
Dim acadApp As Object
Set acadApp = CreateObject(“AutoCAD.Application”)

‘ 何らかの処理(図面を開いて線を引くなど)

‘ 終わり!
MsgBox “処理完了!”
End Sub

【ここがダメ!】
1. `acadApp.Quit` を呼んでいないため、AutoCADに「終了しなさい」という命令がいっていません。
2. プロシージャを抜けた時に変数は消えますが、VBAの裏側にあるCOMの参照カウンタが即座に解放されるとは限らず、VBAが完全にメモリからアンロードされるまでプロセスが残る原因になります。

3. 【解決編】AcadApplicationを完全に解放する極意

では、どうすれば確実にacad.exeを消し去ることができるのでしょうか?
結論から言うと、以下の「3つの鉄則」を順番通りに守る必要があります。

1. 明示的に `Quit` メソッドを呼ぶ
2. オブジェクト変数を `Nothing` にセットして参照を断つ
3. ガベージコレクションのタイミングを意識する(必要ならDoEventsを挟む)

実際の「完璧な終了処理」を含むコードテンプレートを見てみましょう。開発現場でそのままコピペして使えます。

Sub PerfectCleanupExample()
Dim acadApp As Object
Dim isNewInstance As Boolean

On Error GoTo ErrorHandler

‘ 1. 起動中のAutoCADを取得、なければ新規起動
On Error Resume Next
Set acadApp = GetObject(, “AutoCAD.Application”)
If acadApp Is Nothing Then
Set acadApp = CreateObject(“AutoCAD.Application”)
isNewInstance = True
End If
On Error GoTo ErrorHandler ‘ エラー監視を復帰

‘ 可視化する(必要に応じて)
acadApp.Visible = True

‘ ==========================================
‘ ここに実際の自動化処理を書く
‘ ==========================================
MsgBox “AutoCADの操作を行います。OKを押すと終了処理に入ります。”, vbInformation, “確認”

‘ 2. マクロ側から起動したインスタンスの場合のみ、明示的にQuitを呼ぶ
‘ (元々起動していたユーザーのAutoCADを勝手に落とさないための配慮です)
If isNewInstance Then
acadApp.Quit
End If

CleanUp:
‘ 3. 【最重要】オブジェクト変数を必ず Nothing に解放する
‘ ここで変数とCOMオブジェクトの絆を断ち切ります
Set acadApp = Nothing

‘ VBAのガベージコレクションに息継ぎをさせる(念のための保険)
DoEvents

MsgBox “AutoCADは正常に終了し、メモリも解放されました!”, vbInformation, “完了”
Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub

4. チーフアーキテクトが教える、裏の仕組みとさらなるテクニック

上記のコードにある `Set acadApp = Nothing` と `DoEvents`。これには深い理由があります。

`Set = Nothing` の順序と意味

複数のオブジェクト(`AcadApplication` から `AcadDocument`、さらに `AcadModelSpace` など)階層的に取得している場合、「子から親へ」の順序で `Nothing` を代入していくのがCOMプログラミングの鉄則です。

‘ 階層構造がある場合の解放順序の例
Set acadEnt = Nothing
Set acadModel = Nothing
Set acadDoc = Nothing
Set acadApp = Nothing

末端のオブジェクトの参照が1つでも残っていると、親である `AcadApplication` も連鎖してメモリに残ってしまいます。

なぜ `DoEvents` が必要なのか?

VBAはシングルスレッドで動く古い言語です。オブジェクトを解放する命令を出しても、Windowsの裏側のCOMランタイムがそれを処理し終えるまでにわずかなタイムラグが生じることがあります。
`DoEvents` を挟むことで、OSに処理の小休止を与え、確実にメモリ解放の完了を促すことができるのです。プロの間では「おまじない」ではなく「確実なセーフティネット」として愛用されています。

まとめ

いかがでしたでしょうか?
AutoCAD VBAにおけるゾンビプロセス問題は、「オブジェクトのライフサイクル」を意識するだけで完全にコントロール下に置くことができます。

  • 起動したら、必ず `Quit` を検討する(元々開いていたものかどうかの判定も大事)。
  • 使い終わった変数は必ず `Set xxx = Nothing` で解放する。
  • 階層構造があるときは、末端から順に解放する。

ここさえクリアすれば、あなたの組んだマクロはプロ顔負けの堅牢性を手に入れます。
ぜひ、今日のコードから取り入れて、快適なAutoCAD自動化ライフを満喫してくださいね!

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