Jump to content

Recommended Posts

Posted

Good afternoon,

I hope someone can help.

 

I am trying to make a simple LISP routine that creates a script file, opens, and does stuff to all the files in a folder, then closes and saves each file

 

I think this bit works.

 

What isn't happening is that the temporary Script file is hanging about and isn't deleted at the end of the routine - it would be quite nice if it was.

 

So here is what I have (simplified a bit but its got the important parts in)... how do I get the temporary file, f, to be deleted at the end?

 

(defun c:batchlisp( / batchdirectory batchfileslist l)

;;get folder. 
 (setq batchdirectory "C:\\Desktop\\New folder\\")

;;get files list from folder
 (setq batchfileslist (vl-directory-files batchdirectory "*.dwg" nil)) ;;list of files in mylispfolder location.
 (foreach x batchfileslist (setq l (cons (strcat batchdirectory x) l))) ;;make file name full file path
 (if l (setq batchfileslist (reverse l))) ;;make file list 'l' to be batchfileslist


;;Create and open script file
 (setq tempscript (vl-filename-mktemp nil nil ".scr")) ;;temp script file
 (setq f (open tempscript "w")) ;;open file

 (setq acount 0) ;; a counter

 (foreach n batchfileslist
   (progn
     (write-line (strcat "_.OPEN \"" (nth acount batchfileslist) "\"") f) ;;open the drawing
;;
;;Do what I want it to do
;;
     (write-line "_.CLOSE" f) ;;close the drawing
     (write-line "n" f) ;;'n' to save the drawing (change this about later)
   )
   (setq acount (+ 1 acount))
 )
 (close f)

 (command "_.SCRIPT" tempscript) ;;run script
 (vl-file-delete tempscript) ;;delete script file

 (princ "OK")
 (princ)
)

 

 

When I run this I get "OK", and then "_.OPEN" in the command line, I suspect that the file, f, isn't closed properly and hence can't be deleted? I might be wrong

 

 

Thanks in advance

Posted

This is not possible because AutoLISP runs within the active document namespace, therefore when the Script takes focus and opens another document, evaluation of the active AutoLISP program ceases. Consequently, invocation of the Script file should always be the last operation performed by such programs.

 

I account for this in my Batch Attribute Editor program and much older Script Writer program by always using a Script File with a predetermined name and overwriting such file for every use.

Posted

Alternatively you can add a line to your script that will erase the file. This can even be the first line in the script.

(write-line (strcat "(vl-file-delete " (vl-prin1-to-string tempscript) ")"))

Posted

Thanks!

 

Lee a great explanation and I understand why it won't delete now which makes the other ideas make sense. I've seen your batch attribute editor and script writer but wanted to understand how this all works a bit better and see what I could do with it.

 

I'll have a look at all 3 methods tomorrow. Simplest might be to just copy and past Roy's line into the end of the script (20 seconds?), then Lee's idea of a fixed name that is overwritten and because I would have to type that all out would take 30 seconds. And the recycle bin idea? I ike that but would need to look on google to see if it can be done (a fixed name in the recycle bin might be the most efficient)

Posted

@Steven, you're most welcome - glad it helps.

 

@Roy, good idea - I'd not previously considered that approach.

Posted

Change this line to a hard coded file.SCR name and your delete file line also.

 

(setq tempscript (vl-filename-mktemp nil nil ".scr")) 
(setq tempscript "c:\\Acadtemp\\".scr") 

Posted (edited)

just a little experiment I did last week :

 

 


;-------------------------------------------------------- Rlx_AcadCoreScript ------------------------------------------------------
; Had to process 50Gb of data fixing xref paths (server name changed...again) just to discover odbx only saves in native AutoCad version
; In the end had to convert 2000 drawings to autocad 2010 (because of old viewer used by document control system on our site)
; Standard script annoyed me, too slow (much slower than odbx anyway) , also (in odbx) not working was the following :
; (setq acadObj (vlax-get-acad-object) prefObj (vla-get-Preferences acadObj)) (vla-put-SaveAsType (vla-get-OpenSave prefObj) ac2010_dwg)
; I use "Scripting.FileSystemObject" this time because of the huge number of drawings and folders I have to scan everytime
;
; Note that the AutoCad Core has some restrictions (google it , I aint your mama)
; Biggest advantage of batch is that your AutoCad is free as soon as batch executes because coreconsole does all the computing
;
; more information on the AutoCad Core Console :
; [url]http://through-the-interface.typepad.com/through_the_interface/2012/03/commands-that-work-in-the-autocad-2013-core-console.html[/url]
;
; written by Rlx - 11 jan 2018 , last update 16 jan 2018
;------------------------------------------------------------------------------------------------------------------------------------------
(defun c:Rlx_AcadCoreScript ( / prog-base err scr sf dwg-list l dwg)
 (Rlx_AcadCoreScript_Init)
 (if (and (setq sf (getfolder "Select source folder drawings"))
   (setq scr (getfiled "Select script file" "" "scr" 0))
   (vl-consp (setq dwg-list (fido sf))))
   (progn
     (setq start (car (_vl-times)))
     (princ (strcat "\nProcessing " (setq l (itoa (length dwg-list))) " drawings..."))
     ;(Rlx_AcadCoreScript_StartProcessing1)
      (Rlx_AcadCoreScript_StartProcessing2)
     (princ (strcat "\n\nProcessed " l " drawings in " (rtos (/ (- (car (_VL-TIMES)) start) 1000.) 2 4) " secs."))
   )
   (princ "\nNo files to process...")
 )
 (Rlx_AcadCoreScript_Exit)
 (princ)
)
;--- Scripting Object --------------------------------- Begin of Scripting Object ------------------------------------ Scripting Object ---
; Thanks to TonyT - just compressed and tweaked it a little bit
(defun load_fso_scripting ( / server fso:progid fso:prefix )
 (setq fso:progid "Scripting.FileSystemObject" fso:prefix "wsh-")
 (if (not wsh-get-drives)
   (if (not (setq server (CoGetClassServer fso:progid)))
     (alert "Error: Windows Scripting Host is not installed")
     (vlax-import-type-library
:tlb-filename Server :methods-prefix fso:prefix :properties-prefix fso:prefix :constants-prefix (strcat ":" fso:prefix)))))
(defun ProgID->CLSID (ProgID)(vl-registry-read (strcat "HKEY_CLASSES_ROOT\\" progid "[url="file://\\CLSID"]\\CLSID[/url]")))
(defun CoGetClassServer (progid) (CoGetClassProperty progid "InprocServer32"))
(defun CoGetClassProperty (ProgID property / clsid)
 (if (setq clsid (ProgID->CLSID ProgID)) (vl-registry-read (strcat "HKEY_CLASSES_ROOT\\CLSID\\" clsid "\\" property))))
; Find Drawing Objects - test : (setq lst (fido (dos_path "c:/temp/lisp"))) works also with networkpaths
(defun fido ( $f / fso fld rslt)
 (load_fso_scripting)(setq fso (vla-getInterfaceObject (vlax-get-acad-object) "Scripting.FileSystemObject"))
 (setq fld (wsh-GetFolder fso $f) rslt (fifo fld "*.dwg")) (vlax-release-object fld) (vlax-release-object fso) rslt)
; find in folders fl=file ,fls=files, sf=subfolder, sfl=subfolderlist, res=result
(defun fifo ( %dir %ext / fl fls sf sfl res)
 (vlax-for fl (setq fls (wsh-get-files %dir))
   (if (wcmatch (strcase (wsh-get-name fl) t) %ext)(setq res (cons (wsh-get-path fl) res)))(vlax-release-object fl))
 (vlax-release-object fls)
 (vlax-for sf (setq sfl (wsh-get-SubFolders %dir)) (setq res (append res (fifo sf %ext)))(vlax-release-object sf))
 (release_me (list sfl)) res)
;--- Scripting Object ---------------------------------- End of Scripting Object ------------------------------------- Scripting Object ---

;--- Init ----------------------------------------------- Begin of Init section -------------------------------------------------- Init ---
(defun Rlx_AcadCoreScript_Init () (setq err *error*) (defun *error* (s) (princ s)(Rlx_AcadCoreScript_Exit)))
(defun Rlx_AcadCoreScript_Exit ()(setq *error* err))
;--- Init ------------------------------------------------ End of Init section --------------------------------------------------- Init ---

;--- + + + --------------------------------------------- Begin of tiny lisp section --------------------------------------------- + + + ---
(defun wait (sec / stop)(setq stop (+ (getvar "DATE") (/ sec 86400.0)))(while (> stop (getvar "DATE"))))
(defun release_me (lst)
 (mapcar '(lambda(x) (if (and (= 'vla-object (type x))(not (vlax-object-released-p x)))(vlax-release-object x))(set (quote x) nil)) lst))
(defun GetFolder ( msg / fl sh)
 (if (and (setq sh (vlax-create-object "Shell.Application")) (setq fl (vlax-invoke sh 'browseforfolder 0 msg 0 "")))
   (setq fl (vlax-get-property (vlax-get-property fl 'self) 'path)) (setq fl nil)) (release_me (list sh)) fl)
; make sure path is corect for scripting object (dos_path (strcat (getvar "dwgprefix") (getvar "dwgname")))
(defun dos_path  ( $p ) (if (= (type $p) 'str) (strcase (vl-string-translate "/" "\\" $p))   ""))
;--- + + + ---------------------------------------------- End of tiny lisp section ---------------------------------------------- + + + ---

;--- Process-Block -------------------------------------- Begin of Process-Block ---------------------------------------- Process-Block ---
; method 1 : use in loop
(defun Rlx_AcadCoreScript_StartProcessing1 ( / dwg)
 (if (and scr (vl-consp dwg-list))
   (foreach dwg dwg-list
     (command "start" (strcat "accoreconsole.exe /i " "\"" dwg "\"" " /s " "\"" scr "\"" " /l en-us"))
     (wait 1); skip or adjust to match system speed
   )
 )
)
; method 2 : use batch file
(defun Rlx_AcadCoreScript_StartProcessing2 ( / bat dwg)
 (if (and scr (vl-consp dwg-list) (setq fp (open (setq bat "c:\\temp\\tmp.bat") "w")))
   (progn
     (foreach dwg dwg-list
(write-line (strcat "accoreconsole.exe /i " "\"" dwg "\"" " /s " "\"" scr "\"" " /l en-us") fp)
(write-line "timeout /t 1 /nobreak" fp); skip or adjust to match system speed
     )
     (if fp (progn (write-line "exit" fp)(close fp)(gc) (command "start" bat)))
   )
 )
)
;--- Process-Block --------------------------------------- End of Process-Block ----------------------------------------- Process-Block ---
(c:Rlx_AcadCoreScript)

some extra info : http://through-the-interface.typepad.com/through_the_interface/2012/03/commands-that-work-in-the-autocad-2013-core-console.html

 

17 jan : added missing sub and you now can select your own script

 

gr. Rlx

Edited by rlx
  • 2 weeks later...
Posted

Thanks for all the help you gave me so far, my solution was to specify a name for the script file and save that in the temporary folder which seamed to work best for me, this is overwritten each time its used.

 

 

Can I Ask another script question here?

 

Would anyone know if it is possible to validate commands written in a script file before it is run?

 

For example, I might want to Zoom the view, but make a spelling mistake to 'Zom' command.. which then causes a problem... so is there any way to check whether that command is valid?

 

I am guessing the answer is 'no - be more careful how you type' - which is a good answer and I would be thinking the same.

 

Thanks

Posted

Best way is just letting the script run. And even then you have no guarantee it will work on all drawings. Some error catching can be done if you route your commands tru the command-s function. If you search the help function on command-s you can find how to use an error handler. Command-s differs from the normal command in that it first tests the outcome of your command line. You can also use the script only to call a lisp routine where you have the full power of lisp and error catching / decision making.

 

gr. Rlx

Posted

Thanks again, very helpful and I got both methods working. I've copied what I made up here, maybe useful for someone else one day

 

;;works but it can't handle for example 'all' in "ZOOM ALL" written in 1 line.
;;Can also use 'command-s' with similar results

(defun c:commandcheck(mycommand / mycommandlist)
;;my command can be a single word for example, "ZOOM" or a full command "ZOOM ALL", this will check the 1st word is a valid command
 (setq mycommandlist (LM:Str->lst mycommand " ")) ;; Command to a list (get LM:Str-.lst from Lee Macs excellent website)
 (setq mycommand (nth 0 mycommandlist)) ;; get first word of list
 (if (= nil (getcname mycommand)) ;; if 1st word of mycommand not a command
   (progn
     (setq commandOK "Error")
     (alert "Invalid command.")
   )
 )
 (if (/= nil (getcname mycommand))(setq commandOK "OK"))
)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...