Who has my drawing open?
Published on Friday, 31 October 2008 20:16
If you use Autocad in a multi-user environment, you've run into the situation where someone has the drawing open, that you are supposed to be working on. Unless you have Vault running, you have no idea who has it open - short of making the rounds in the Office, or, making phone calls to someone who might have it open remotely.
There is a way to know this - and other information - from VBA. When you open an Autocad drawing, it creates a "lock" file, something like an access database might. Depending on the version of Autocad, it stores the information about User name, Pc Name, and time of last lock, in a hidden file.
We can find, and read this file from VBA - with some caveats. This file is supposed to be erased when the drawing is closed, but, if you crashed previously, this file might remain. So the existence of the file, and/or the data in the file, might not be relevant.
So first we have to check if the drawing is actually used. We can do this with a windows API call, opening the file in "exclusive" mode. This method will fail if the file is opened by any other process, or any other method - it dosnt have to be opened for writing by Autocad.
If the call fails, then we know the Autocad drawing has been opened by someone else, and we can then find, and read the information, in the lock file.
' VBA Module to see who has the current Acad drawing open
' Note we use an Alias here as using the Actual
' function name will not be accepted, because of the underscore in the name
Private Declare Function lOpen Lib "kernel32" Alias "_lopen" (ByVal lpPathName As String, ByVal iReadWrite As Long) As Long
Private Declare Function lClose Lib "kernel32" Alias "_lclose" (ByVal hFile As Long) As Long
' the Constant below:
' Private Const OF_SHARE_EXCLUSIVE = &H10
' OPENS the FILE in EXCLUSIVE mode, denying other processes AND the current
' process both read and write access to the file. If the file has been opened in
' any other mode for read or write access _lopen fails.
Private Const OF_SHARE_EXCLUSIVE = &H10
' Declare Variables up front
Dim MyDocument As AcadDocument
Dim docPath As String, msg As String
Dim retCode As Variant, retVnt As Variant
' get Curent Drawing Object
Set MyDocument = Application.ActiveDocument
If MyDocument Is Nothing Then
MsgBox "There are no documents open in AutoCad.", vbInformation, "Drawing Info"
docPath = MyDocument.FullName ' get the path of the drawing
If docPath = "" Then
MsgBox "This Drawing has not yet been saved to disk. ", vbInformation, "Drawing Info"
If IsFileAlreadyOpen(docPath) = True Then
retVnt = DwgUserInfo(docPath) ' get user Info
If IsEmpty(retVnt) Then ' CANT FIND ACAD LOCK FILE
msg = "This Drawing is not locked by Autocad." & vbCrLf & "It may be locked by another application, like Vault."
MsgBox msg, vbInformation, "Unable to determine status"
msg = "This Drawing is opened by user name: " & retVnt(0) & vbCrLf
msg = msg & "The drawing was opened from computer name : " & retVnt(1) & vbCrLf
msg = msg & "It was last locked on : " & retVnt(2) & vbCrLf
MsgBox msg, vbInformation, "Drawing Information"
' see if it has a read-only attrib set
msg = Dir$(docPath, vbReadOnly)
If msg > "" Then ' it DOES
msg = "This Dwg is not listed as being open by another user."
msg = msg & vbCrLf & "But it does have a Read-Only lock on it." & vbCrLf
msg = msg & "It may be locked by the Vault, or another application."
MsgBox msg, vbExclamation, "Drawing Info"
MsgBox "This Drawing is not listed as being open by another user.", vbInformation, "Who has this open?"
Set MyDocument = Nothing
Private Function IsFileAlreadyOpen(strFullPath_FileName As String) As Boolean
' If this Function succeeds, the return value is a File handle.
' If this Function fails, the return value is HFILE_ERROR = -1
Dim hdlFile As Long, lastErr As Long
hdlFile = -1 ' set to default return code
' Open file for Read/Write and Exclusive Sharing.
hdlFile = lOpen(strFullPath_FileName, OF_SHARE_EXCLUSIVE)
' If we can't open the file, get the last error.
If hdlFile = -1 Then
lastErr = Err.LastDllError
Else ' Make sure we close the file on success!
' Check for sharing violation error.
IsFileAlreadyOpen = (hdlFile = -1) And (lastErr = 32)
Private Function DwgUserInfo(strFullPath As String) As Variant
' returns user info for who opened file,or error message
Dim TrimExt As String
Dim strLen As Integer, I As Integer
Dim DotPosition As Integer, NextFile As Integer
Dim FoundChar As String
Dim LockedByAcad As Boolean
Dim foundFile As String, tmpStr As String
' Declare String Array fr User Info
Dim UserInfo(2) As String
strLen = Len(strFullPath)
' Build a string containing the path to the acad document, and substitute
' the ".dwg" for ".dwl", which is a hidden lock file created by Autocad when
' the drawing is opened by a user.
For I = strLen To 1 Step -1
FoundChar = Mid$(strFullPath, I, 1)
If FoundChar = "." Then ' found last dot
DotPosition = I
TrimExt = Left$(strFullPath, DotPosition)
' Add the Lock file extension
TrimExt = TrimExt & "dwl"
' make sure file is there
foundFile = Dir$(TrimExt, vbHidden)
If foundFile > "" Then
NextFile = FreeFile
Open TrimExt For Input As #NextFile
Line Input #NextFile, tmpStr
DwgUserInfo = Split(tmpStr, Chr$(10))
Else ' NOT LOCKED BY AUTOCAD