【実務・中級編】【上級】AcadApplication.Quit実行時の「未保存図面」一括破棄または強制保存:シャットダウンシーケンスの完全制御 – AutoCAD VBA解析バイブル

スポンサーリンク

【上級】AcadApplication.Quit実行時の「未保存図面」一括破棄または強制保存:シャットダウンシーケンスの完全制御

外部アプリケーション(C#やVB.NET、あるいは別プロセスのVBA)からAutoCADを遥隔操作し、一連のバッチ処理や自動図面生成を完遂させた後――。

最後に待ち構えている最大の罠が、`AcadApplication.Quit` によるシャットダウンの頓挫である。

「よし、全ての処理が終わった。アプリケーションを落とせ」とコードを書いたはずが、裏でAutoCADがひっそりとダイアログを出し、「変更を保存しますか? [はい(Y)/いいえ(N)/キャンセル(C)]」とユーザーのクリックを待ち続けてプロセスがゾンビ化する。完全自動化を目指す開発者にとって、これほど悪夢な光景はない。

今回は、AutoCADのオブジェクトモデルの深層に踏み込み、未保存図面のライフサイクルを完全に掌握し、ユーザーの介入を一切許さずにクリーンかつ安全にAutoCADプロセスを消滅させるためのシャットダウンシーケンスの極意を伝授する。

—

なぜ `AcadApplication.Quit` だけでは沈黙してしまうのか

AutoCADのドキュメント管理モデルにおいて、`AcadDocument` は単なるデータの塊ではない。それぞれのドキュメント(`AcadDocument`)は、自身が「最後に保存されてから変更されたか(Modified)」の状態フラグを持っている。

`AcadApplication.Quit` を呼び出した瞬間、AutoCADは開かれている全ドキュメントのコレクション(`AcadDocuments`)を走査する。もしそこに `Modified = True` のドキュメントが1つでも存在していれば、アプリケーションは安全装置として終了処理を中断し、モーダルダイアログを表示してユーザーに判断を委ねる仕様になっている。

外部連携(ヘッドレス運用やバッチ処理)において、この挙動は致命的なバグとなる。人間が画面の前に張り付いて「いいえ」を押し続けるシステムなど、自動化とは呼べない。

したがって、我々エンジニアは、`Quit` を呼び出す前に、すべてのドキュメントの運命(保存するのか、破棄するのか)をプログラム側で完全にコントロールし尽くさなければならない。

—

堅牢なシャットダウン設計の原則

実務の現場で通用する堅牢なコードを書くためには、以下の3つの鉄則を守る必要がある。

1. 警告表示の無効化 (`DisplayAlerts` またはシステム変数)
AutoCAD内部のダイアログやアラートを抑制し、意図しないフリーズを防ぐ。
2. ドキュメントコレクションの逆順走査(または確実なループ)
コレクションを閉じながらループを回す際の前方インデックスのズレを防ぐ。
3. エラーハンドリングとプロセスの強制刈り取り(フォールバック)
万が一、COMオブジェクトの解放に失敗した場合の最終防衛ラインを用意する。

—

【実用コード】完全制御シャットダウン・モジュール

以下に、外部または内部から安全にAutoCADを終了させ、未保存図面の「全破棄」または「強制保存」を選択できるプロダクションコードを示す。

Option Explicit

”’

”’ AutoCADを安全かつ完全に終了させるためのマスタープロシージャ
”’

”’ True: 変更を保存して終了 / False: 変更をすべて破棄して終了 Public Sub ForceShutdownAutoCAD(ByVal saveChanges As Boolean)
Dim acadApp As Object
Dim acadDocs As Object
Dim doc As Object
Dim i As Long

On Error GoTo ErrorHandler

‘ 実行中のAcadApplicationインスタンスを取得(遅延バインディングによる堅牢性確保)
On Error Resume Next
Set acadApp = GetObject(, “AutoCAD.Application”)
On Error GoTo ErrorHandler

If acadApp Is Nothing Then
‘ すでにAutoCADが起動していない場合は何もしない
Exit Sub
End If

‘ ユーザーインターフェースからのアラートを抑制
‘ (※AutoCADのバージョンやAPI仕様により効かない場合があるため、ドキュメントごとの制御が必須)
acadApp.DisplayAlerts = False

Set acadDocs = acadApp.Documents

If Not acadDocs Is Nothing Then
‘ コレクションの数から1まで逆順でループを回す
‘ (図面を閉じることでインデックスがズレるのを防ぐため、これは鉄則)
For i = acadDocs.Count To 1 Step -1
Set doc = acadDocs(i)

‘ 図面が読み取り専用でなく、かつ変更されている場合のみ処理
If Not doc.ReadOnly Then
If saveChanges Then
‘ 強制保存(パスが未設定の新規図面の場合は名前をつけて保存のロジックが必要だが、
‘ 今回は既存ファイルの変更保存を想定。必要に応じて Path プロパティをチェック)
If doc.Path <> “” Then
doc.Save
Else
‘ 未保存の新規図面で、保存を選択した場合のフォールバック
‘ doc.SaveAs “C:\Temp\AutoSaved_” & Format(Now, “yyyymmdd_hhmmss”) & “.dwg”
End If
Else
‘ 変更を破棄するため、保存済みフラグを強制的に偽(False)に偽装する
‘ ※これを行うことで、「保存しますか?」ダイアログのトリガーを回避できる
doc.Saved = True
End If
End If

‘ ドキュメントを閉じる(保存確認ダイアログはすでに回避されている)
doc.Close False
Next i
End If

‘ すべてのドキュメントが閉じられた状態でアプリケーションを終了
acadApp.Quit

‘ オブジェクト変数の解放
Set doc = Nothing
Set acadDocs = Nothing
Set acadApp = Nothing

Exit Sub

ErrorHandler:
‘ 異常終了時のフォールバック:プロセス自体の強制終了(タスクキル)
‘ ※COMオブジェクトが応答しない場合の最終手段
Call ForceKillProcess(“acad”)

MsgBox “AutoCADのシャットダウン中にエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “強制終了ハンドラー”
End Sub

”’

”’ 万が一のゾンビプロセス対策:OSレベルでプロセスを強制終了する
”’

Private Sub ForceKillProcess(ByVal processName As String)
On Error Resume Next
CreateObject(“WScript.Shell”).Run “taskkill /f /im ” & processName & “.exe”, 0, True
End Sub

—

コードの急所:なぜ `doc.Saved = True` が「神の一手」なのか

上記のコード内で、変更を破棄 (`saveChanges = False`) するルートに以下の記述を入れている。

doc.Saved = True
doc.Close False

これが本記事における最大の知見である。

AutoCADの内部COM仕様において、`Document.Close` メソッドの引数(`SaveChanges`)は用意されているものの、アプリケーション全体の終了シーケンス(`Quit`)と連動した際、未保存フラグが立っているドキュメントが存在すると、この引数が無視されてモーダルダイアログが暴発することが多々ある。

あらかじめ `doc.Saved = True`(「この図面は保存済みである」という偽りのフラグ)をプログラムから書き込んでおくことで、AutoCADの変更検知メカニズムを巧みにバイパスし、ユーザーへの確認ダイアログを一切出させずに安全に `Close` および `Quit` に持ち込むことが可能になる。

このテクニックを知っているか否かで、バックグラウンド連携システムの安定性が文字通り「桁違い」になる。

—

データベース連携・ファイルI/Oにおける注意点

もしこのシャットダウンシーケンスの直前まで、外部データベース(Access, SQL Server等)や外部ファイル(CSV/JSON)との間でトランザクション処理を行っていた場合、以下の順序を厳守しなければならない。

1. DBの接続閉鎖(Connection Close)
2. AutoCAD図面の保存・破棄(今回のシャットダウン処理)
3. AutoCADアプリケーション自体の解放(`Quit`)

AutoCADのプロセスが完全にメモリから消滅する(OSのタスクマネージャーから `acad.exe` が消える)までには、わずかにタイムラグが存在する。外部プログラムから連続してAutoCADを起動・終了させるバッチ処理を組む場合は、`Quit` 実行後に数秒のウェイト(`Sleep`)を入れるか、プロセスが完全に消滅したことをポーリングで確認する堅牢なラッパー設計を取り入れるべきだ。

まとめ

AutoCAD VBA、ひいては外部からのAutoCAD制御における「美しさ」とは、裏で動くプロセスがユーザーの画面を汚さず、エラーを吐かず、静かに、そして確実にお仕事を完了させて消えていくことにある。

今回解説したドキュメントコレクションの逆順走査、フラグの制御、そしてタスクキルによる最終防衛ライン。これらを実装に組み込むことで、あなたの業務自動化システムは「人間の手助けを必要とするおもちゃ」から「24時間止まらない真のプロダクションツール」へと昇華する。

プロのエンジニアとしての誇りを持ち、細部までコントロールされたコードベースを構築してほしい。

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