Let's make a .dwl3

Let's make a .dwl3

lane.hargroder
Contributor Contributor
1,133 Views
9 Replies
Message 1 of 10

Let's make a .dwl3

lane.hargroder
Contributor
Contributor

Hello, All,

 

I would like to mimic the .dwl and .dwl2 functionality of AutoCAD for the purpose of correcting an issue created by hosting our shared work files on SharePoint/OneDrive. I am not looking for suggestions on other places to save our files. The issue is that .dwl and .dwl2 files are constantly "in-use" from the moment they're created, and so OneDrive does not sync them to the cloud, and therefore other users are allowed to open the same drawing files without being prompted to open them read-only because AutoCAD does not detect that the file is in use. To remedy this, my goal is to create a lisp routine that is loaded for each drawing via acaddoc.lsp that creates a temporary .dwl3 file when a drawing is opened and deletes it when the file is closed. Because it will be a static file, it will get synced, and I can include in my code a check for the existence of this file when opening drawings, and warn users if someone else may have it open.

I still have a lot of improvements to make, but below is my very basic attempt at getting started, which is doing everything it's supposed to do other than deleting the .dwl3 file on close. I am getting a "no function definition: ADD-REACTOR" error, which is likely the culprit, but I'm a bit clueless on how to fix it. Calling the deletedwl3file function directly does in fact delete the text file successfully, so I'm just left trying to figure out how to get CLOSE and QUIT to trigger it. Also need to account for if CLOSE or QUIT is cancelled, but maybe that's a problem for the future.

Any help would be appreciated!

 

(defun c:writedwl3file (/ user txt des)
  (setq user (getvar "loginname"))
  (setq txt (strcat (getvar "Dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3")) ; Excluded the extension from dwgname

  (if (findfile txt)
      (alert "Warning: This file may be in use by another user. Please open the .dwl3 file in Notepad for more information.")
  )

  (if (setq des (open txt "w"))
      (progn 
          (write-line (strcat "This MSA file lock was created by " user ".") des) 
          (close des) 
      ) 
      (princ "\nUnable to create text file.") 
  )
)

(c:writedwl3file) ; This line ensures writedwl3file is executed upon loading dwl3.lsp

;;-----------------------------------------------------------

(defun c:deletedwl3file ()
  (setq txt (strcat (getvar "Dwgprefix")(substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3")) ; Excluded the extension from dwgname
  (if (findfile txt)
      (vl-file-delete txt)
  )
  (princ)
)

;;-----------------------------------------------------------

(defun reactor_close_drawing (event)
  (c:deletedwl3file)
)

(vl-load-com)
(add-reactor 'Dwg_Close reactor_close_drawing)

 

0 Likes
Accepted solutions (2)
1,134 Views
9 Replies
Replies (9)
Message 2 of 10

Sea-Haven
Mentor
Mentor

This is something I use it has all the do stuff removed. Thanks to help from others here that made it work.

 

 

; by AlanH April 2023

;Reactor callback function
(defun BeginCloseFunc (reactor lst / blocks blk efname ent2 ent3 ole olelst ssole oletit olefound  ss ssvft y tabname)

DO STUFF HERE

(cond
((= (vlr-current-reaction-name) ':VLR-beginSave) (Princ "\nThis function has been triggered by a Document Save event."))
((= (vlr-current-reaction-name) ':VLR-beginClose)(princ "\nThis function has been triggered by a Document Close event."))
)
(princ)
)
(if (not _BeginCloseReactor) (setq _BeginCloseReactor (VLR-Dwg-Reactor nil '((:VLR-beginClose . BeginCloseFunc)))))
(if (not _BeginSaveReactor ) (setq _BeginSaveReactor  (VLR-Dwg-Reactor nil '((:VLR-beginSave  . BeginCloseFunc)))))

 

 

0 Likes
Message 3 of 10

MrJSmith
Advocate
Advocate

Alan, do close reactors work? For some reason I am remember not getting them to work....I know the open document reactors don't work so I could just be misremembering.

0 Likes
Message 4 of 10

lane.hargroder
Contributor
Contributor

Thank you both for the input. I've actually got the close reactor behaving as it should. Now I seem to have another issue to resolve. A "Yes" response to my Popup is supposed to execute my openreadonly function, but instead I get "error: Automation Error. Invalid execution context".

 

What is strange is that if I then appload the whole code again, the popup happens again and this time it works. So from the acaddoc.lsp instance of the code, I get the error, if I manually load it, it works as intended.

 

Any ideas?

 

;;----- Popup  -  Lee Mac ---------------------------------

;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)

;;----- Open Read-Only ------------------------------------

(defun OpenReadOnly ()
  (vl-load-com)
  (setq dwgPath (getvar "DWGPREFIX"))
  (setq fileName (getvar "DWGNAME"))
  (setq dwg (strcat dwgPath fileName))
  
  (setq docs (vla-get-documents (vlax-get-acad-object)))
  (setq activeIndex (1- (vla-get-count docs))) ; Save active drawing index value
  
  (vla-open docs dwg :vlax-true)
  
(vla-sendcommand (vla-item docs activeIndex) "_.CLOSE ") ;

)

;;----- Read DWL3 -----------------------------------------

(defun c:readdwl3file ()
  (setq dwl (strcat (getvar "Dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3"))
  (setq file (findfile dwl))
  (if file
    (progn
      (setq data "")
      (setq file (open dwl "r"))
      (if file
        (setq data (read-line file))
      )
      (close file)
      (if data
        (setq data (strcase (vl-string-trim " " data)))
        (setq data "none")
      )
    )
    (setq data "none")
  )
  (prompt data)
)

;;----- Write DWL3 ----------------------------------------

(defun c:writedwl3file ()
  (setq user (getvar "loginname"))
  (setq dwg (strcat (getvar "Dwgprefix") (getvar "dwgname")))
  (setq dwl (strcat (getvar "Dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3"))


  (setq dwlowner (c:readdwl3file))

  (if (not (findfile dwl))
      (progn
        (if (setq des (open dwl "w"))
            (progn 
                (write-line user des) 
                (close des) 
            ) 
            (princ "") 
        )
      )

(setq readonly (LM:popup "AutoCAD Alert" "filenameandpath.dwg is currently in use by: dwlowner. Would you like to open the file read-only?" (+ 4 16 4096)))

  )
)

;;----- Delete DWL3 ---------------------------------------

(defun c:deletedwl3file ()
  (setq dwl (strcat (getvar "Dwgprefix")(substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3")) ; Excluded the extension from dwgname
  (if (findfile dwl)
      (vl-file-delete dwl)
  )
  (princ)
)

;;----- Close Reator - Lee Mac (Modified) -----------------

(defun CloseReactor nil
  (vl-load-com)

  (   (lambda ( data / react )
        (if (setq react
                  (vl-some
                    (function
                      (lambda ( reactor )
                        (if (eq data (vlr-data reactor)) reactor)
                      )
                    )
                    (cdar
                      (vlr-reactors :vlr-editor-reactor)
                    )
                  )
                )
            (if react
                (if (vlr-added-p react)
                    (vlr-remove react)
                    (vlr-add react)
                )
            )
            (setq react
                  (vlr-editor-reactor data
                                       (list
                                        (cons :vlr-beginclose 'CustomCloseCallBack)
                                        )
                                       )
                  )
            )
        (setq *error* nil) ; Suppress any potential error messages

        (if (vlr-added-p react)
            (setq status "Close reactor is on")
            (setq status "Close reactor is off")
        )

        )

      "Close-Reactor"
    )
)

(defun CustomCloseCallBack (reactor arguments)
  
(c:deletedwl3file) ; Deletes .dwl3 file when closing or quitting

  (vlr-remove reactor) ; Ensure the reactor is removed after it's triggered
)

;;-----------------------------------------------------------

(closereactor)

(c:writedwl3file)

(if (= readonly 6)
      (and (closereactor) (openreadonly))
(if (= readonly 7)
      (and (closereactor) (command "close" "No"))
      (princ "")))

 

 

 

 

0 Likes
Message 5 of 10

MrJSmith
Advocate
Advocate

@lane.hargroder Your problem appears to be the fact you want to open the current drawing as read only and close it.

 

(vla-open docs dwg :vlax-true) ;Opening drawing as read only
(vla-sendcommand (vla-item docs activeIndex) "_.CLOSE ") ;closing current drawing

 

This action isn't possible as the drawing that gets opened would end the command. The new opened drawing wouldn't enter the LISP to close the old drawing. You can get around this issue by setting up a vl-set-bb variable that gets checked every time during in the acdoc. I'd set the variable to the drawing vla doc so you could close it after the file gets opened. 

Another issue is the .dwl3 file seems to get deleted if you open the file as read-only and then close it. Attempted to fix that by adding the closerector only if the variable to close the open drawing is nil. However, you may have to make it so the reactor only runs if username of the file is not the current username.

 

This is what I currently have; unfortunately, I am unable to test it fully since I don't have the same setup/issue as your cloud hosted files.

 

;;----- Popup  -  Lee Mac ---------------------------------

;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)

;;----- Open Read-Only ------------------------------------

(defun OpenReadOnly ()
	(vl-load-com)
	(setq dwgPath (getvar "DWGPREFIX"))
	(setq fileName (getvar "DWGNAME"))
	(setq dwg (strcat dwgPath fileName))
	(setq docs (vla-get-documents (vlax-get-acad-object)))
	(vl-bb-set 'oldDwgToClose (vla-get-ActiveDocument (vlax-get-acad-object))) ;Set the drawing to close 
	(vla-open docs dwg :vlax-true) ;Open the drawing as read only
)

;;----- Read DWL3 -----------------------------------------

(defun readdwl3file ()
  (setq dwl (strcat (getvar "Dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3"))
  (setq file (findfile dwl))
  (if file
    (progn
      (setq data "")
      (setq file (open dwl "r"))
      (if file
        (setq data (read-line file))
      )
      (close file)
      (if data
        (setq data (strcase (vl-string-trim " " data)))
      )
    )
  )
  data
)

;;----- Write DWL3 ----------------------------------------

(defun writedwl3file ()
	(setq user (getvar "loginname"))
	(setq dwg (strcat (getvar "Dwgprefix") (getvar "dwgname")))
	(setq dwl (fnsplitl dwg)) ;fnsplitl -- undocumented lisp function that returns a list with  (path fileName extension)
	(setq dwl (strcat (car dwl) (cadr dwl) ".dwl3"))

	(if (not (findfile dwl))
		(progn
			(if (setq des (open dwl "w"))
				(progn 
					(write-line user des) 
					(close des) 
				) 
				(princ "\nUnable to create text file.") 
			)
		)
		(progn 
			(setq dwlowner (readdwl3file)) ;File exists, read it
			(setq readonly (LM:popup "AutoCAD Alert" (strcat dwg ": Is currently in use by: " dwlowner ". Would you like to open the file read-only?") (+ 4 16 4096)))
		)
	)

	(if (= readonly 6) ;User wants to open file in read only
		(and (closereactor) (openreadonly))
		(if (= readonly 7) ;User doesn't want to open file in read only, close current file
			(and (closereactor) (command "close" "No"))
			(princ "")
		)
	)

)

;;----- Delete DWL3 ---------------------------------------

(defun deletedwl3file ()
  (setq dwl (strcat (getvar "Dwgprefix")(substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3")) ; Excluded the extension from dwgname
  (if (findfile dwl)
      (vl-file-delete dwl)
  )
  (princ)
)

;;----- Close Reator - Lee Mac (Modified) -----------------

(defun CloseReactor nil
  (vl-load-com)

  (   (lambda ( data / react )
        (if (setq react
                  (vl-some
                    (function
                      (lambda ( reactor )
                        (if (eq data (vlr-data reactor)) reactor)
                      )
                    )
                    (cdar
                      (vlr-reactors :vlr-editor-reactor)
                    )
                  )
                )
            (if react
                (if (vlr-added-p react)
                    (vlr-remove react)
                    (vlr-add react)
                )
            )
            (setq react
                  (vlr-editor-reactor data
                                       (list
                                        (cons :vlr-beginclose 'CustomCloseCallBack)
                                        )
                                       )
                  )
            )
        (setq *error* nil) ; Suppress any potential error messages

        (if (vlr-added-p react)
            (setq status "Close reactor is on")
            (setq status "Close reactor is off")
        )

        )

      "Close-Reactor"
    )
)

(defun CustomCloseCallBack (reactor arguments)
  
	(deletedwl3file) ; Deletes .dwl3 file when closing or quitting
	(vlr-remove reactor) ; Ensure the reactor is removed after it's triggered
)

;;-----------------------------------------------------------

(writedwl3file)
(if (vl-bb-ref 'oldDwgToClose) ;Close the drawing you attempted to open
	(progn 
		(vl-bb-set 'oldDwgToClose nil)
		(vla-Close (vl-bb-ref 'oldDwgToClose) :vlax-false)
	)
	(closereactor) 
)

 

 

0 Likes
Message 6 of 10

lane.hargroder
Contributor
Contributor

@MrJSmith, thank you for the input, but I don't think you've identified the issue.

 

For a little more context... my acaddoc.lsp has the following:

(if (= (getvar "WRITESTAT") 1)

(load "H:\\CAD\\C3D\\LSP\\dwl3.lsp")

)

 

Where dwl3.lsp is the entirety of the code I previously posted. This addresses your concern regarding the .dwl3 file getting deleted if you open the file as read-only and then close it. The code does not load for drawings opened read-only, so the .dwl3 is not deleted in that case.

 

Regarding the first problem you mentioned, I'm not sure that I follow. Keep in mind, if I don't have anything in my acaddoc.lsp, and instead I just open the file and then APPLOAD dwl3.lsp, everything works as intended, including the openreadonly function when yes to the popup is chosen (assuming a .dwl3 file is found). If dwl3.lsp is loaded from acaddoc.lsp, however, the error occurs.

 

Regarding testing, you don't need to have the cloud issue to test if things are working properly:

 

  1. Create a dwl3.lsp file with my code in it
  2. Temporarily revise your acaddoc.lsp to read as mine does above
  3. Create a test.dwg
  4. create a test.dwl3 in the same folder (using notepad)
  5. Open test.dwg and you'll get the popup. If you choose no, it closes properly, if you choose yes, error
  6. Now remove the load dwl3.lsp from acaddoc.lsp
  7. Open test.dwg again and make sure the test.dwl3 file still exists
  8. APPLOAD dwl3.lsp
  9. Now the popup happens again, no still works, and now yes does too.

All that to say, the error hinges on whether the dwl3.lsp is called from acaddoc.lsp while opening the drawing or from APPLOAD after the drawing is already open.

 

So the simpler question is: why does this work when loaded manually but not when loaded automatically from acaddoc.lsp?

0 Likes
Message 7 of 10

MrJSmith
Advocate
Advocate
Accepted solution

@lane.hargroder You are correct. I followed your steps and got it working. The issue is you are creating race conditions. AutoCAD is not fully loaded by the time you want to run scripts. One method ACAD offers to slow the process down is the s::startup function which runs AFTER everything has been fully loaded. Usually this isn't important, but in this case it matters due to the nature of your script you are writing.

 

I eliminated your other race condition with closing the file by saving the file doc to the black board variable and then calling the close on the other drawing by switching to it and picking it up in the startup function readOnlyCheck.

 

Here is the working code that you can paste into your acdoc.lsp. (Note: I could not get findfile to work with the .dwl3. It ALWAYS returned nil for me when running it in startup, even if I hardcoded the path. However, by changing it to .info, it could see the file. Currently the code is working with .info but if it works with .dwl3 for you, then do a find replace of .info for .dwl3)

 

 

 

 

(defun customStartupFuncs()
	(writedwl3file)
	(readOnlycheck)
)
(if (not *customRunOnce*) ;AutoCAD gets a hissy fit if you try to modify the s::startup function after it has already ran. Variable to prevent this when reloading lisp files.
	(progn
		(if s::startup
			(setq s::startup (append s::startup (quote ((customStartupFuncs)))))
			(defun s::startup () (customStartupFuncs))
		)
		(setq *customRunOnce* 1)
	)
)

;;----- Popup  -  Lee Mac ---------------------------------

;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)

;;----- Open Read-Only ------------------------------------

(defun OpenReadOnly ()
	(vl-load-com)
	(setq dwgPath (getvar "DWGPREFIX"))
	(setq fileName (getvar "DWGNAME"))
	(setq dwg (strcat dwgPath fileName))
	(setq docs (vla-get-documents (vlax-get-acad-object)))
	(vl-bb-set 'oldDwgToClose (vla-get-ActiveDocument (vlax-get-acad-object))) ;Set the drawing to close 
	(vla-open docs dwg) ;Open the drawing as read only
	(vlax-for it (vla-get-documents (vlax-get-acad-object)) ;Get the new document object, same name but read only
		(if (and (= (strcase (vla-get-name it) (strcase fileName))) (= :vlax-true (vla-get-readonly it)))
			(setq newDoc it)
		)
	)
	(vla-activate newDoc) ;Switch to the new document
)

;;----- Read DWL3 -----------------------------------------

(defun readdwl3file (dwl) ;dwl is the complete dwlFileName Path
  (setq file (findfile dwl))
  (if file
    (progn
      (setq data "")
      (setq file (open dwl "r"))
      (if file
        (setq data (read-line file))
      )
      (close file)
      (if data
        (setq data (strcase (vl-string-trim " " data)))
      )
    )
  )
  data
)

;;----- Write DWL3 ----------------------------------------

(defun writedwl3file ()
	(if (not (vl-bb-ref 'oldDwgToClose))
		(progn
			(setq user (getvar "loginname"))
			(setq dwg (strcat (getvar "Dwgprefix") (getvar "dwgname")))
			(setq dwl (fnsplitl dwg)) ;fnsplitl -- undocumented lisp function that returns a list with  (path fileName extension)
			(setq dwl (strcat (car dwl) (cadr dwl) ".info"))
			; (print (findfile "C:\\Users\\jsmith\\Desktop\\Testland\\Export.dwg" ))
			(if (not (findfile dwl))
				(progn
					(if (setq des (open dwl "w"))
						(progn 
							(write-line user des) 
							(close des) 
						) 
						(princ "\nUnable to create text file.") 
					)
				)
				(progn 
					
					(setq dwlowner (readdwl3file dwl)) ;File exists, read it
					
					(setq readonly (LM:popup "AutoCAD Alert" (strcat dwg ": Is currently in use by: " dwlowner ". Would you like to open the file read-only?") (+ 4 16 4096)))
				)
			)

			(if (= readonly 6) ;User wants to open file in read only
				(and (closereactor) (openreadonly))
				(if (= readonly 7) ;User doesn't want to open file in read only, close current file
					(and (closereactor) (command "close" "No"))
					(princ "")
				)
			)
		)
	)

)

;;----- Delete DWL3 ---------------------------------------

(defun deletedwl3file ()
  (setq dwl (fnsplitl (strcat (getvar "Dwgprefix")(getvar "dwgname"))))
  (setq dwl (strcat (car dwl)(cadr dwl)".info"))
  
  (if (findfile dwl)
      (vl-file-delete dwl)
  )
  (princ)
)

;;----- Close Reator - Lee Mac (Modified) -----------------

(defun CloseReactor nil
  (vl-load-com)

  (   (lambda ( data / react )
        (if (setq react
                  (vl-some
                    (function
                      (lambda ( reactor )
                        (if (eq data (vlr-data reactor)) reactor)
                      )
                    )
                    (cdar
                      (vlr-reactors :vlr-editor-reactor)
                    )
                  )
                )
            (if react
                (if (vlr-added-p react)
                    (vlr-remove react)
                    (vlr-add react)
                )
            )
            (setq react
                  (vlr-editor-reactor data
                                       (list
                                        (cons :vlr-beginclose 'CustomCloseCallBack)
                                        )
                                       )
                  )
            )
        (setq *error* nil) ; Suppress any potential error messages

        (if (vlr-added-p react)
            (setq status "Close reactor is on")
            (setq status "Close reactor is off")
        )

        )

      "Close-Reactor"
    )
)

(defun CustomCloseCallBack (reactor arguments)
	(deletedwl3file) ; Deletes .dwl3 file when closing or quitting
	(vlr-remove reactor) ; Ensure the reactor is removed after it's triggered
)

;;-----------------------------------------------------------

(defun readOnlycheck ()
	(if (vl-bb-ref 'oldDwgToClose) ;Close the drawing you attempted to open
		(progn 
			(vla-Close (vl-bb-ref 'oldDwgToClose) :vlax-false)
			(vl-bb-set 'oldDwgToClose nil)
		)
		(closereactor) 
	)
)

 

 

 

0 Likes
Message 8 of 10

lane.hargroder
Contributor
Contributor

@MrJSmith, thank you thank you thank you, but still getting some errors...

First attempt resulted in...

error: no function definition: DEBUG

 

I'm not sure what the  (debug "dwlowner: " dwlowner) line is doing, but if I erase it...

 

I do get the popup but...

 

If I select yes, the drawing opens in read-only, but the old drawing doesn't close

 

If I select no, the drawing closes, but the .info file is deleted when it shouldn't be. The (closereactor) is supposed to be toggled so that that doesn't happen, but that doesn't seem to be working as it should.

0 Likes
Message 9 of 10

MrJSmith
Advocate
Advocate

@lane.hargroder Sorry, thought I had removed all the debug. I have removed it from the post as of now.

 

Not sure why it isn't closing the drawing. It works via the test you suggested above. Tested it both in AutoCAD 2018 & 2023.

 

As for the closereactor not working properly, I agree. But I didn't bother attempting to fix it because you said you had a working solution for it already.

0 Likes
Message 10 of 10

lane.hargroder
Contributor
Contributor
Accepted solution

@MrJSmith, I greatly appreciate all the help. I have not confirmed your final code works as intended, but I've marked it as a solution based on your testing. Ultimately, I just ended up reducing the functionality of my own code so that instead of asking if you'd like to open read-only and automating it, it just warns you that it's open with an alert box and closes the drawing once hitting OK. I also opted to handle the case of opening a file read-only from within the code itself rather than a conditional load from acaddoc.lsp.

 

So, my acaddoc.lsp has the following:

 

(load "H:\\CAD\\C3D\\LSP\\dwl3.lsp")

 

 

and dwl3.lsp looks like this:

 

 

;;----- Popup  -  Lee Mac ---------------------------------

;; A wrapper for the WSH popup method to display a message box prompting the user.
;; ttl - [str] Text to be displayed in the pop-up title bar
;; msg - [str] Text content of the message box
;; bit - [int] Bit-coded integer indicating icon & button appearance
;; Returns: [int] Integer indicating the button pressed to exit

(defun LM:popup ( ttl msg bit / wsh rtn )
    (if (setq wsh (vlax-create-object "wscript.shell"))
        (progn
            (setq rtn (vl-catch-all-apply 'vlax-invoke-method (list wsh 'popup msg 0 ttl bit)))
            (vlax-release-object wsh)
            (if (not (vl-catch-all-error-p rtn)) rtn)
        )
    )
)

;;----- Read DWL3 -----------------------------------------

(defun c:readdwl3file ()
  (setq dwl (strcat (getvar "Dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3"))
  (setq file (findfile dwl))
  (if file
    (progn
      (setq data "")
      (setq file (open dwl "r"))
      (if file
        (setq data (read-line file))
      )
      (close file)
      (if data
        (setq data (strcase (vl-string-trim " " data)))
        (setq data "none")
      )
    )
    (setq data "none")
  )
  data
)

;;----- Write DWL3 ----------------------------------------

(defun c:writedwl3file ()
  (setq user (getvar "loginname"))
  (setq dwg (strcat (getvar "Dwgprefix") (getvar "dwgname")))
  (setq dwl (strcat (getvar "Dwgprefix") (substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3"))


(setq dwlowner (c:readdwl3file))
(if (null dwlowner)
    (setq dwlowner "unknown")
)

  (if (not (findfile dwl))
      (progn
        (if (setq des (open dwl "w"))
            (progn 
                (write-line user des) 
                (close des) 
            ) 
            (princ "") 
        )
      )

(and (saveclosereactor) (and (LM:popup "AutoCAD Alert" (strcat dwg " is currently in use by " dwlowner ". Please open the file read-only.") (+ 0 16 4096)) (command "close" "No")))

  )
)

;;----- Delete DWL3 ---------------------------------------

(defun c:deletedwl3file ()
  (setq dwl (strcat (getvar "Dwgprefix")(substr (getvar "dwgname") 1 (- (strlen (getvar "dwgname")) 4)) ".dwl3")) ; Excluded the extension from dwgname
  (if (findfile dwl)
      (vl-file-delete dwl)
  )
  (princ)
)

;;----- SaveClose Reator - Lee Mac (Modified) -----------------

(defun SaveCloseReactor nil
  (vl-load-com)

  (   (lambda ( data / react )
        (if (setq react
                  (vl-some
                    (function
                      (lambda ( reactor )
                        (if (eq data (vlr-data reactor)) reactor)
                      )
                    )
                    (cdar
                      (vlr-reactors :vlr-editor-reactor)
                    )
                  )
                )
            (if react
                (if (vlr-added-p react)
                    (vlr-remove react)
                    (vlr-add react)
                )
            )
            (setq react
                  (vlr-editor-reactor data
                                       (list
                                        (cons :vlr-beginclose 'CustomCloseCallBack)
                                        (cons :vlr-savecomplete 'CustomSaveCallBack)
                                        )
                                       )
                  )
            )
        (setq *error* nil) ; Suppress any potential error messages

        (if (vlr-added-p react)
            (setq status "SaveClose reactor is on")
            (setq status "SaveClose reactor is off")
        )

        )

      "SaveClose-Reactor"
    )
)

(defun CustomCloseCallBack (reactor arguments)
  
 (if (= (getvar "WRITESTAT") 1)
     (c:deletedwl3file)
 ) ; Deletes .dwl3 file when closing or quitting a read-write file

  (vlr-remove reactor) ; Ensure the reactor is removed after it's triggered
)

(defun CustomSaveCallBack (reactor arguments)
  
(and (c:deletedwl3file) (c:writedwl3file)) ; Saves a new .dwl3 when saving

)

;;-----------------------------------------------------------

(saveclosereactor)

(if (= (getvar "WRITESTAT") 1)
     (c:writedwl3file)
 ) ; Writes .dwl3 file when opening a read-write file

 

 

While it doesn't look identical to the native file-locking system, it accomplishes what I need it to, and hopefully it's helpful to others out there dealing with the same issues.