【入門編】【上級プロフェッショナル向け】Windows APIを用いた「ファイル使用中(ロック)」の完全判定と待機キューの実装 – AutoCAD VBA解析バイブル

スポンサーリンク

こんにちは!AutoCAD VBAの荒波を航海中のエンジニアの皆さん、調子はいかがですか?

「マクロの記録」から一歩踏み出し、自分だけの自動化スクリプトを書けるようになると、本当に世界が変わりますよね。ボタン一つで何百枚もの図面が処理されていく快感は、一度味わうと病みつきになります。

さて、今回は少し背伸びをして、「現場で絶対に避けて通れない実務の壁」を一緒に突破しましょう。テーマは【Windows APIを用いた「ファイル使用中(ロック)」の完全判定と待機キューの実装】です。

「えっ、いきなりAPI?難しそう……」と思いましたか?
大丈夫、安心してください。今回は優しく、かつ本質的なところまで徹底的に噛み砕いて解説します。ここをクリアすれば、あなたの書くAutoCAD VBAコードは、一気に「プロのエンジニアのそれ」にランクアップしますよ。

—

なぜ、普通のVBAコードではネットワーク図面の処理でコケるのか?

皆さんは、社内の共有サーバー(NASやファイルサーバー)にあるDWGファイルをVBAで一括処理しようとして、こんなエラーに悩まされたことはありませんか?

  • 「ファイルは別の人によって開かれているため、読み取り専用で開きますか?」というダイアログが出て、プログラムがフリーズする。
  • 運悪くそのダイアログを見逃すと、プログラムが止まったままランチタイムに突入してしまう。

通常、VBAの `Workbooks.Open` のような感覚で `Documents.Open` を使っても、ファイルが排他制御(ロック)されているときの挙動をスマートにコントロールするのは至難の業です。特にネットワーク越しの場合、他のデザイナーが図面を開いているかどうかの判定は、AutoCADの標準機能だけではタイムラグや例外エラーを生みがちです。

ここで登場するのが、WindowsのOS機能そのものに直接アクセスする「Windows API(Application Programming Interface)」です。

—

Windows APIの力:ファイルを「安全に覗き見する」

Windowsの世界では、ファイルが開かれているとき、そのファイルには「ロック(排他制御)」という鍵がかけられます。
VBAから「このファイル、今鍵がかかってる?」とWindowsのKernel32(カーネル32:Windowsの心臓部のようなDLL)に直接尋ねることで、AutoCAD本体が悲鳴を上げる前に、安全かつ高速にファイルの生死(使用中かどうか)を判定できるのです。

今回は、ファイルを開く権利を独占せずに「ちょっと開けるかテストさせて」と要求するAPI関数、`CreateFile` を使ったテクニックをご紹介します。

—

実装コード:ファイルロック判定 & 待機キューシステム

以下のコードを、あなたのVBAモジュールにそのまま貼り付けてみてください。
実務でそのまま使えるように、「ファイルがロックされていたら、指定秒数だけリトライ(待機)し、それでもダメならスキップする」という優れものの待機キュー(Queue)ロジックを組み込んでいます。

Option Explicit

‘ — Windows API の宣言 —
‘ ファイルやデバイスを作成・オープンし、そのハンドル(識別子)を取得する関数
Private Declare PtrSafe Function CreateFile Lib “kernel32” Alias “CreateFileA” ( _
ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As LongPtr

‘ 開いたファイルのハンドルを閉じる関数
Private Declare PtrSafe Function CloseHandle Lib “kernel32″ ( _
ByVal hObject As LongPtr) As Long

‘ 定数定義
Private Const GENERIC_READ = &H80000000
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_EXISTING = 3
Private Const INVALID_HANDLE_VALUE = -1

”
‘ 指定されたファイルが他のプロセスによってロックされているかを判定する関数
‘ @param filePath 調査するファイルのフルパス
‘ @return True = 使用可能(ロックなし), False = 使用中(ロック中)
‘
Public Function IsFileAvailable(ByVal filePath As String) As Boolean
Dim hFile As LongPtr

‘ ファイルを「読み取り専用・共有モード」で開こうと試みる
‘ 他人が書き込み用で開いている場合、このAPIは失敗(INVALID_HANDLE_VALUEを返す)する
hFile = CreateFile( _
filePath, _
GENERIC_READ, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
0, _
OPEN_EXISTING, _
0, 0)

If hFile = INVALID_HANDLE_VALUE Then
‘ ロックされている(誰かが開いている)
IsFileAvailable = False
Else
‘ ロックされていない(安全に開ける)
IsFileAvailable = True
‘ 開いたハンドルはすぐに閉じる(リソースリークを防ぐための重要な作法!)
, Call CloseHandle(hFile)
End If
End Function

”
‘ 【メイン処理】ファイルロックが解除されるまで待機(キューイング)し、
‘ 解除され次第、AutoCADで安全に図面を開くプロシージャ
‘
Public Sub SafeOpenDrawingWithQueue()
Dim targetPath As String
targetPath = “C:\SharedFolder\DesignData\SampleDrawing.dwg” ‘ ※実環境のパスに変更してください

Dim maxRetry As Long
Dim waitSeconds As Long
Dim currentRetry As Long

‘ — 設定値 —
maxRetry = 5 ‘ 最大リトライ回数
waitSeconds = 3 ‘ 1回あたりの待機秒数
currentRetry = 0

Do
‘ 1. ファイルが利用可能かAPIでチェック
If IsFileAvailable(targetPath) Then
MsgBox “ファイルのロックが解除されています。AutoCADで図面を開きます。”, vbInformation

‘ ここで通常のAutoCAD図面オープン処理を呼び出す
‘ 例: ThisDrawing.Application.Documents.Open targetPath
Exit Sub
End If

‘ 2. ロック中の場合の処理(待機キューの動作)
currentRetry = currentRetry + 1
If currentRetry > maxRetry Then
MsgBox “タイムアウトしました。” & vbCrLf & _
“該当ファイルは現在他のユーザーによって占有されています。処理をスキップします。”, vbExclamation
Exit Sub
End If

‘ 3. 指定秒数だけ処理を一時停止し、サーバーへの負荷やCPU使用率の跳ね上がりを防ぐ
‘ ※VBAの Sleep は 32bit/64bit環境の違いでハングしやすいため、DoEventsを挟んだ待機ループを推奨
Call SmartWait(waitSeconds)

Loop
End Sub

”
‘ CPUを占有せずにスマートに待機するためのヘルパー関数
‘
Private Sub SmartWait(ByVal seconds As Long)
Dim startTimer As Single
startTimer = Timer
Do While Timer < startTimer + seconds DoEvents ' OSに制御を返し、AutoCADがフリーズするのを防ぐ Loop End Sub ---

ここがエンジニアの腕の見せ所!コードの急所を解説

1. `CreateFile` の魔術的な使い方
このコードの肝は、実際にAutoCADでファイルを開くのではなく、Windowsに対して「ちょっとこのファイル、覗かせてもらうよ(`GENERIC_READ`)」と声をかける点です。もし他の人が編集目的で開いていると、Windowsは「ダメです」と門前払い(`INVALID_HANDLE_VALUE`)します。これを利用して、ファイルを開かずにロック状態をミリ秒単位で看破しています。

2. リソースの解放(`CloseHandle`)の絶対厳守
APIを使ってファイルを開いたら、絶対にハンドルを閉じなければなりません(`CloseHandle`)。これを忘れると、VBAからそのファイルに永遠にアクセスできなくなる「リソースリーク」というメモリの病気を引き起こします。プログラマーの基本にして最大の鉄則です。

3. `SmartWait` によるCPU優しさ設計
「ファイルを待つ」ときに、ただ闇雲にループを回すと、PCのCPU使用率が100%に張り付いてファンが爆音で回り始めます。`DoEvents` を挟んだタイマー制御を入れることで、AutoCADやOSの動作を妨げずに、優しく順番待ち(キュー)を実行できるのです。

—

まとめ:ここをクリアすれば、もう怖くない!

今回は、Windows APIの扉を少しだけ叩いて、ネットワーク共有環境におけるファイルロックの完全制御を見てきました。

「マクロの記録」の延長線上のコードだと、誰かが図面を開いていただけでエラーで止まってしまうツールしか作れません。しかし、今回のような「OSレベルの状態を監視し、賢く待機・判断する仕組み」を手に入れたあなたなら、夜間に何百枚もの図面を自動処理する「無人バッチシステム」だって構築可能です。

エラーに怯える日々は今日で終わりです。ぜひご自身の開発環境にこの知見を組み込み、ワンランク上のAutoCAD自動化ライフを満喫してください。

それでは、次回の極限知見でお会いしましょう。良きVBAライフを!

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