Hi all,
Is it possible to dermine the "Last Modified" date through LISP?
I store our LISP files on the LAN and I make updates/improvements often. I have a progn that finds the files and copies them to the local machine. The files are then loaded. This has been a very reliable method of distributing the ".lsp" throughout all offices. Yet, my one wish is that I could determin (through LISP) if the files on the LAN have been modified more recently than the files on the local machine, then I could run the progn so that everyone is using the latest version each day.
*Why? Many times I get called away to resolve issues with the ".lsp" bugs-n-stuff, and far more often than not, the drafter is simply using a file that is months old and the issue is already resolved.
Thanks.
Solved! Go to Solution.
Solved by Lee_Mac. Go to Solution.
Why not point each machine at the network location? Update the LAN file once and the rest of them automatically see the change.
Alternatively, make a batch file that runs when the user logs in and copies the file(s) down.
EDIT: One more thing is that if you do have the lisp routine check to see whether or not it's up-to-date, you'll need to either update the local copy or force acad to read the file from the LAN side. OR you'll need to manually copy the file locally (or have them do it). Because short of having your lsp routine open the LAN copy for read and the local copy for write and then reading/writing line-by-line, there's no way to have lsp update the local copy.
Don Ireland
Engineering Design Technician
Easiest method, is to read the files from a read-only centralized location for your officially published code. Zero-touch.
Somewhat less (but still absurdly) easy is to use a BAT file with the XCOPY command and appropriate modifiers for only-copy-if-newer. Light-touch, can be called by login script.
Thanks for the replies 🙂
I am the onlyone to touch the LAN copy. I edit my local version and run a LISP that deletes the LAN copy then copies the local version to the LAN location. The counterpart LISP deletes the local copy then copies the LAN file to the localmachine.
I found a progn that Lee Mac wrote: "_lastmodified" @ http://www.theswamp.org/index.php?topic=43559.msg488184#msg488184
The time/date is returned as a real number so I was able to do a simple (> file1 file2) to determine the newer of the two.
Thank you all for the tips.
Happy to help - even if indirectly!
If you did want to go the vl-file-systime route, you could use something like this:
;; Returns T if f1 has been modified more recently than f2 (defun newer-p ( f1 f2 / compare ) (defun compare ( a b ) (cond ( (> (car a) (car b))) ( (and a b (= (car a) (car b))) (compare (cdr a) (cdr b)) ) ) ) (apply 'compare (mapcar '(lambda ( x ) (vl-list* (car x) (cadr x) (cdddr x))) (mapcar 'vl-file-systime (list f1 f2)) ) ) )
You're welcome mid-awe, let me know how you get on
Why bother with doing this yourself, this sounds like it is just ordinary file synchronization, for which there are already plenty of existing, fully debugged programs available.
http://en.wikipedia.org/wiki/File_synchronization
Another question, why copy .lsp files? Unless your programs are mutually exclusive or extremely large, you could compile the whole bunch into a single .vlx file, and load it directly from the network disk. (Or from local copy, if needed for stand-alone operation. Still, only need to check one file date.).
- We have a single .vlx file containing about 1700 defuns, being loaded by the acaddoc.lsp file.
--
This sub-function is exactly what I'm looking for as well but not understanding how to make this work in my program. I'm thinking that this is a sub-function that I can call in my function using newer-p somehow, I get errors.
If this returns T, I would like for it to copy over a set of files to destination location but can't seem to make that work. Any suggestions on a function that would do that calling this sub-function for evaluation?
This is my sad attempt at it:
(setq F1 "") (setq F2 "") (defun newer-p ( F1 F2 / compare ) (defun compare ( a b ) (cond ( (> (car a) (car b))) ( (and a b (= (car a) (car b))) (compare (cdr a) (cdr b)) ) ) ) (apply 'compare (mapcar '(lambda ( x ) (vl-list* (car x) (cadr x) (cdddr x))) (mapcar 'vl-file-systime (list F1 F2)) ) ) ) (defun c:UpdateFiles ( F1 F2 / ) (if (equal (newer-p (F1 F2)) T) (princ "File 1 is newer") (princ "File 1 is not newer") ) )
(defun newer-p ( f1 f2 / compare ) (defun compare ( a b ) (cond ( (> (car a) (car b))) ( (and a b (= (car a) (car b))) (compare (cdr a) (cdr b)) ) ) ) (apply 'compare (mapcar '(lambda ( x ) (vl-list* (car x) (cadr x) (cdddr x))) (mapcar 'vl-file-systime (list f1 f2)) ) ) ) (setq file1 "someFile" file2 "someOtherFile" ) (if (newer-p file1 file2) (princ (strcat file1 " is newer than " file2)) (princ (strcat file1 " is NOT newer than " file2)) )
Seems I had the idea, just not the syntax! Thanks so much, this is fantastic.
@Lee_Mac wrote:Happy to help - even if indirectly!
If you did want to go the vl-file-systime route, you could use something like this:
;; Returns T if f1 has been modified more recently than f2 (defun newer-p ( f1 f2 / compare ) (defun compare ( a b ) (cond ( (> (car a) (car b))) ( (and a b (= (car a) (car b))) (compare (cdr a) (cdr b)) ) ) ) (apply 'compare (mapcar '(lambda ( x ) (vl-list* (car x) (cadr x) (cdddr x))) (mapcar 'vl-file-systime (list f1 f2)) ) ) )
I know this is old, but just a heads up in case someone else comes across this, Lee's code only seems to compare the date, not the time, so if the file is modified on the same date, it will always return T, no matter what.
In case anyone needs one here is version I have come up with:
(defun IsNewer (File_1 File_2 / FileSystem Date_1 Date_2 Results Obj_File_1 Obj_File_2) ;Returns T if File_1 is newer than File_2
(setq File_1 (findfile File_1)
File_2 (findfile File_2)
)
(if (and File_1 File_2)
(progn
(setq FileSystem (vlax-get-or-create-object "scripting.filesystemobject"))
(if FileSystem
(progn
(setq Obj_File_1 (vlax-invoke FileSystem 'getfile File_1)
Obj_File_2 (vlax-invoke FileSystem 'getfile File_2)
)
(if (and Obj_File_1 Obj_File_2)
(progn
(setq Date_1 (vlax-get Obj_File_1 'datelastmodified)
Date_2 (vlax-get Obj_File_2 'datelastmodified)
)
(if (and Date_1 Date_2)
(progn
(if (> Date_1 Date_2)
(setq Results T)
)
)
)
)
)
(vlax-release-object FileSystem)
)
)
)
)
Results
)
I am sure this is not perfect, but it seems to get the job done.
@chriswade FWIW your code could be condensed to this:
(defun isnewer (file_1 file_2 / filesystem date_1 date_2 obj_file_1 obj_file_2)
;; Returns T if File_1 is newer than File_2
(and (setq file_1 (findfile file_1))
(setq file_2 (findfile file_2))
(setq filesystem (vlax-get-or-create-object "scripting.filesystemobject"))
(setq obj_file_1 (vlax-invoke filesystem 'getfile file_1))
(setq obj_file_2 (vlax-invoke filesystem 'getfile file_2))
(setq date_1 (vlax-get obj_file_1 'datelastmodified))
(setq date_2 (vlax-get obj_file_2 'datelastmodified))
(or (vlax-release-object filesystem) t)
(> date_1 date_2)
)
)
*update to release object
For security resons, I'd just replace this line :
(vlax-release-object filesystem)
with this :
(or (vlax-release-object filesystem) t)
Out of curiosity, can either of you please explain why (or (vlax-release-object filesystem) t) is better from a security standpoint?