Paul Li Posted Sunday at 05:09 PM Posted Sunday at 05:09 PM Attached is an improved version of getfiled that implements powershell with the option to select single or multiple files returning a list of the selected item(s): Examples: (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 0) ; for single selection of file type dwg (pl:getfiledps "Select Files" (strcat (getenv "userprofile") "\\downloads") "dwg;dxf" 1) ; for multiple selection of file types dwg & dxf Feedback & comments are welcome. pl_getfiledps.lsp 5 Quote
SLW210 Posted Monday at 11:40 AM Posted Monday at 11:40 AM Many work computers are likely limited for using Powershell. Unrelated to Powershell being blocked, I get an error loading. error: string too long on input Quote
Steven P Posted Monday at 12:06 PM Posted Monday at 12:06 PM String too long - just a guess, file path and file name string length? - going back old school when we had 256? characters for it all - but just a guess Quote
SLW210 Posted Monday at 12:28 PM Posted Monday at 12:28 PM I'm not going to troubleshoot it since Powershell is blocked at work, but if the load has that error, then it's something in the Code, probable in the DCL write-line part. 1 Quote
Paul Li Posted Monday at 09:11 PM Author Posted Monday at 09:11 PM Thanks for troubleshooting. That could definitely be caused by having a write-line statement that's way too long. I've made the changes to reduce the write-line on the dcl. Kindly troubleshoot some more for offices that do allow for running powershell with the attached revised version...thanks in advance. pl_getfiledps.lsp Quote
GLAVCVS Posted Monday at 11:43 PM Posted Monday at 11:43 PM (edited) One observation: in older versions of AutoCAD (2000 and 2002, at least), 'vla-get-HWND' applies to the Document object rather than the Acad object. Edited Monday at 11:45 PM by GLAVCVS 1 Quote
BIGAL Posted Monday at 11:49 PM Posted Monday at 11:49 PM (edited) Works great often do old fashioned DOS to get file names list or use the VL files functions. A suggestion remove "result" from the local variables list. As the answer disappears. Or ; Example: ; (setq files (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 1)) A side comment I have used Powershell with Bricscad and sometimes does not work. Your code may help as you do a deeper dive into running Powershell. I generally only do a "Power shell and script" I have used it to change programs, I jump to Excel from CAD. Edited Monday at 11:51 PM by BIGAL 1 Quote
Paul Li Posted Tuesday at 04:48 PM Author Posted Tuesday at 04:48 PM On 9/14/2026 at 5:28 AM, SLW210 said: I'm not going to troubleshoot it since Powershell is blocked at work, but if the load has that error, then it's something in the Code, probable in the DCL write-line part. Could you test if this PowerShell-p function would return nil on your powershell blocked computers? ; PowerShell-p function to check if powershell is available to run...Returns T if available (defun PowerShell-p (/ shell result) (setq shell (vlax-create-object "WScript.Shell") result (vl-catch-all-apply 'vlax-invoke-method (list shell 'Run "powershell.exe -NoProfile -Command \"exit 0\"" 0 T)) ) (vlax-release-object shell) (and (not (vl-catch-all-error-p result)) (= result 0) ) ) Quote
Paul Li Posted Tuesday at 04:49 PM Author Posted Tuesday at 04:49 PM 17 hours ago, GLAVCVS said: One observation: in older versions of AutoCAD (2000 and 2002, at least), 'vla-get-HWND' applies to the Document object rather than the Acad object. so does the pl:getfiledps function still run properly on those older AutoCAD versions? Quote
SLW210 Posted Tuesday at 09:35 PM Posted Tuesday at 09:35 PM 21 hours ago, GLAVCVS said: One observation: in older versions of AutoCAD (2000 and 2002, at least), 'vla-get-HWND' applies to the Document object rather than the Acad object. 4 hours ago, Paul Li said: so does the pl:getfiledps function still run properly on those older AutoCAD versions? Yes, I was working on that for my home computer with 2000i. Since I had some home time today with AutoCAD 2000i, I did some updating to your code. Seems to work great with minimal testing. Here is my Test Code... ; ================================================================ ; Test command ; ================================================================ (defun c:SelectDWGs (/ files) (setq files (pl:getfiledps "Select DWG Files" (getvar "DWGPREFIX") "dwg" 1 ) ) (if files (progn (princ "\nSelected files:" ) (foreach file files (princ (strcat "\n" file ) ) ) ) (princ "\nNo files selected." ) ) (princ) ) pl_getfiledps_2000i.lsp 3 Quote
Paul Li Posted Tuesday at 10:27 PM Author Posted Tuesday at 10:27 PM @SLW210 Your revised version works beautifully and can now support older versions of AutoCAD...thanks a bunch!!! Quote
GLAVCVS Posted Wednesday at 02:47 PM Posted Wednesday at 02:47 PM (edited) 22 hours ago, Paul Li said: so does the pl:getfiledps function still run properly on those older AutoCAD versions? Yes: as @SLW210 says, it seems to work well. On the other hand: Have you considered having the script written only if it does not already exist in the expected directory, and keeping PowerShell running from the initial load? This would make the dialog box load faster on subsequent calls. In this regard, the script check/creation could be done when the code is loaded. This would also improve the speed of the first execution slightly. Edited Wednesday at 02:51 PM by GLAVCVS 1 Quote
Paul Li Posted Wednesday at 07:15 PM Author Posted Wednesday at 07:15 PM @GLAVCVS thanks for the feedback. I assume to use a single Powershell session you would have to run a batch file that launches Powershell first before starting autocad? Then when autocad closes or crashes out that session of Powershell also closes. 1 Quote
SLW210 Posted Thursday at 10:44 AM Posted Thursday at 10:44 AM I added a note in the file where to change to keep PowerShell open. ; ---------------------------------------------------------- ; Wait until PowerShell finishes. ; ---------------------------------------------------------- (vlax-invoke-method shell "Run" cmd 0 ; <=== Change 0 to 1 if you want PowerShell to stay open. :vlax-true ) (vlax-release-object shell) ) ) I was running some tests at work to see if there was a method to determine if PowerShell was blocked to give a message... (princ "\nPowerShell access is blocked.") (princ "\nPowerShell access is allowed.")) Right now all I get on the commandline is... error: Automation Error. Description was not provided. Though I had to get to some of my "paid to do" work done yesterday. This is probably above my pay grade. I just realized who the OP is, a big time Guru over at Autodesk forums and AUGI. 2 Quote
GLAVCVS Posted 8 hours ago Posted 8 hours ago On 9/16/2026 at 9:15 PM, Paul Li said: @GLAVCVS thanks for the feedback. I assume to use a single Powershell session you would have to run a batch file that launches Powershell first before starting autocad? Then when autocad closes or crashes out that session of Powershell also closes. You can start a PowerShell instance from LISP and keep it running in the background, ready to receive instructions. I've played around with this idea a little and ended up with the following code. I haven't tested it thoroughly enough, so its robustness could probably be improved. But it may be useful. (defun PS-START (/ fp sh cmd n) (vl-load-com) ;| -------------------------------------------------------------- Si existe READY, suponemos de momento que ya está funcionando. Posteriormente podemos hacer PS-ALIVE más rigurosa. |; -------------------------------------------------------------- (setq *PS-SERVER* (strcat (getenv "TEMP") "\\PL_PS_Server.ps1") *PS-TCMD* (strcat (getenv "TEMP") "\\PL_PS_Command.tmp") *PS-CMD* (strcat (getenv "TEMP") "\\PL_PS_Command.txt") *PS-OUT* (strcat (getenv "TEMP") "\\PL_PS_Output.txt") *PS-READY* (strcat (getenv "TEMP") "\\PL_PS_Ready.txt") ) (if (findfile *PS-READY*) T (progn ;|Clean previous files / Limpiar archivos anteriores|; (if (findfile *PS-CMD*) (vl-file-delete *PS-CMD*) ) (if (findfile *PS-OUT*) (vl-file-delete *PS-OUT*) ) ;|Create server script / Crear script servidor|; (setq fp (open *PS-SERVER* "w")) ;|Nombres de los archivos de comunicación|; (write-line "$cmd = $env:TEMP + '\\PL_PS_Command.txt'" fp) (write-line "$out = $env:TEMP + '\\PL_PS_Output.txt'" fp) (write-line "$ouTmp = $env:TEMP + '\\PL_PS_Output.tmp'" fp) (write-line "$ready = $env:TEMP + '\\PL_PS_Ready.txt'" fp) ;|Indicate Powershelll ready / Señalizar que PowerShell está preparado|; (write-line "Set-Content -Path $ready -Value $PID -Encoding Default" fp) ;|Main loop / Bucle principal Powershell remains here for entire session / PowerShell permanece aquí durante toda la sesión|; (write-line "while ($true) {" fp) ;|Is there any pending request? / ¿Hay una orden pendiente?|; (write-line " if (Test-Path $cmd) {" fp) ;|Read ALL code / Leer TODO el código. -Raw permite que PS-EXEC pueda mandar scripts de varias líneas, no solamente una instrucción |; (write-line " $code = Get-Content -Path $cmd -Raw -Encoding Default" fp) ;|Delete request inmediately / Borrar la petición inmediatamente. Esto indica que el servidor ya se ha hecho cargo de ella.|; (write-line " Remove-Item $cmd -Force" fp) ;|Orden para terminar el servidor|; (write-line " if ($code.Trim() -eq '__EXIT__') {" fp) (write-line " break" fp) (write-line " }" fp) ;|Execute code IN THIS POWERSHELL SESSION / Ejecutar código EN ESTA MISMA SESIÓN POWERSHELL|; (write-line " try {" fp) (write-line " $result = Invoke-Expression $code" fp) ;| OUT must always be created so that PS-EXEC knows the process has finished Hay que crear siempre OUT. Incluso si la expresión devuelve $null necesitamos crear el archivo para que PS-EXEC sepa que hemos terminado. |; (write-line " if ($null -eq $result) {" fp) (write-line " Set-Content -Path $ouTmp -Value '' -Encoding Default" fp) (write-line " }" fp) (write-line " else {" fp) (write-line " $result | Out-File -FilePath $ouTmp -Encoding Default" fp) (write-line " }" fp) (write-line " Move-Item $ouTmp $out -Force" fp);rename PL_PS_Output.tmp / renombramos PL_PS_Output.tmp ;|Capturar errores|; (write-line " }" fp) (write-line " catch {" fp) (write-line " ('__ERROR__ ' + $_.Exception.Message) | Out-File -FilePath $out -Encoding Default" fp) (write-line " }" fp) ; close / cerrar 'IF Test-Path' (write-line " }" fp) ;| Sleep / Demorar 10 ms. Prevents resident Powershell instance from continuously using a CPU core while it has nothing to do Evita que el PowerShell residente utilice continuamente un núcleo de CPU mientras no tiene nada que hacer |; (write-line " Start-Sleep -Milliseconds 10" fp) ; cerrar WHILE (write-line "}" fp) ;|PowerShell está terminando|; (write-line "Remove-Item $ready -Force -ErrorAction SilentlyContinue" fp) (close fp) ;|Arrancar PowerShell|; (setq cmd (strcat "powershell.exe " "-NoLogo " "-NoProfile " "-NonInteractive " "-STA " "-ExecutionPolicy Bypass " "-WindowStyle Hidden " "-File \"" *PS-SERVER* "\"" ) ) (setq sh (vlax-create-object "WScript.Shell")) (vlax-invoke-method sh 'Run cmd 0 :vlax-false) (vlax-release-object sh) ;| Esperar a que PowerShell cree READY Máximo: 5 segundos |; (setq n 0) (while (and (not (findfile *PS-READY*)) (< n 500) ) (repeat 10000 (getvar "MILLISECS")) (princ "\rEsperando...") (setq n (1+ n)) ) ;|Result / Resultado|; (if (findfile *PS-READY*) T nil ) ) ) ) (defun PS-EXEC (code / fp lin result t0) ;| Clears any previous result / Borrar posible resultado anterior|; (if (findfile *PS-OUT*) (vl-file-delete *PS-OUT*) ) ;| Write code that Powershell should executed / Escribir el código que debe ejecutar PowerShell|; (setq fp (open *PS-CMD* "w")) (write-line code fp) (close fp) ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-TOUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-TOUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) ;| Delete result / Borrar resultado|; (vl-file-delete *PS-OUT*) (reverse result) ) (defun PL-FILEDIALOG-INIT (/ hwnd) ;; HWND de ESTA instancia concreta de AutoCAD (setq hwnd (vla-get-HWND (if (minusp (- (atoi (getvar "ACADVER")) 16)) (vla-get-activeDocument (vlax-get-acad-object)) (vlax-get-acad-object))) ) ;; Windows Forms + OpenFileDialog (PS-EXEC (strcat "Add-Type -AssemblyName System.Windows.Forms;" "$script:f=New-Object System.Windows.Forms.OpenFileDialog" ) ) ;|Small 'wrapper' to convert AutoCAD's HWND into a valid 'IWin32Window' for ShowDialog(owner) Pequeño 'wrapper' para convertir el HWND de AutoCAD en un 'IWin32Window' válido para 'ShowDialog (owner)' |; (PS-EXEC (strcat "Add-Type -TypeDefinition " "'using System;" "using System.Windows.Forms;" "public class WindowWrapper:IWin32Window{" "private IntPtr h;" "public WindowWrapper(IntPtr hwnd){h=hwnd;}" "public IntPtr Handle{get{return h;}}" "}' " "-ReferencedAssemblies System.Windows.Forms" ) ) ;|Locate AutoCAD and create owner Localizar AutoCAD y crear el 'owner' |; (PS-EXEC (strcat "$script:owner=New-Object WindowWrapper(" (itoa hwnd) ")" ) ) T ) (defun pl:getfiledps (title dir ext flg / psquote makefilter code) ;| Escape / Escapar ' PowerShell|; (defun psquote (s / p n) (setq n 0) (while (setq p (vl-string-search "'" s n)) (setq s (strcat (substr s 1 p) "''" (substr s (+ p 2))) n (+ p 2) ) ) s ) (defun makefilter (s / p r x) (setq r "") (while (setq p (vl-string-search ";" s)) (setq x (substr s 1 p) r (strcat r "*." x ";") s (substr s (+ p 2)) ) ) (strcat r "*." s) ) ;|Default values / Valores por defecto|; (if (/= (type title) 'STR) (setq title "Select Files") ) (if (not (and (= (type dir) 'STR) (vl-file-directory-p dir) ) ) (setq dir (getvar "DWGPREFIX")) ) (if (= (type ext) 'STR) (setq ext (makefilter ext)) (setq ext "*.dwg") ) ;| Build only the code needed for this call: Powershell, Forms, f and owner ALREADY EXISTS Construir únicamente el código necesario para ESTA llamada: PowerShell, Forms, f y owner YA EXISTEN |; (setq code (strcat "$script:f.FileName='';" "$script:f.Title='" (psquote title) "';" "$script:f.InitialDirectory='" (psquote dir) "';" "$script:f.Filter='Files (" ext ")|" ext "';" "$script:f.Multiselect=" (if (and (= (type flg) 'INT) (/= flg 0) ) "$true;" "$false;" ) "$r=$script:f.ShowDialog($script:owner);" "if($r -eq " "[System.Windows.Forms.DialogResult]::OK)" "{$script:f.FileNames}" ) ) ;| Execute in the resident Powershell instance / Ejecutar en PowerShell residente |; (PS-EXEC code) ) ;|If Powershell is not already running, start a instance / SI POWERSHELL NO ESTÁ INSTANCIADO, SE CREA UNA INSTANCIA|; (if (not *PS*) (progn (setq *PS* (PS-Start)) (PL-FILEDIALOG-INIT))) How does it work?... When the code is loaded, a PowerShell instance and a base script are created. After that, simply call the pl:getfiledps function whenever you need it. Quote
Paul Li Posted 5 hours ago Author Posted 5 hours ago @GLAVCVS Thanks for the modified code. But I'm encountering the following errors after attempting to load it: ; error: bad argument type: stringp nil The error is caused by the following lines of code under the PS-EXEC function: ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-TOUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-TOUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) When I change the following lines of code referencing *PS-TOUT* to what you had commented out using *PS-OUT* then at least it'll load successfully: ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-OUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-OUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) But after this when I call the pl:getfiledps function using the following line of code: (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 1) The Select Files window would appear on top of my AutoCAD session and then just hang there. I'm unable to select any files from this window or move the window out of the way: I would have to terminate the AutoCAD app from Task Manager But the Select Files window remains. Now the window is freed up for me to select files and drag the window around. Any thoughts as to why this is occurring on my end? Quote
GLAVCVS Posted 2 hours ago Posted 2 hours ago 3 hours ago, Paul Li said: @GLAVCVS Thanks for the modified code. But I'm encountering the following errors after attempting to load it: ; error: bad argument type: stringp nil The error is caused by the following lines of code under the PS-EXEC function: ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-TOUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-TOUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) When I change the following lines of code referencing *PS-TOUT* to what you had commented out using *PS-OUT* then at least it'll load successfully: ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-OUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-OUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) But after this when I call the pl:getfiledps function using the following line of code: (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 1) The Select Files window would appear on top of my AutoCAD session and then just hang there. I'm unable to select any files from this window or move the window out of the way: I would have to terminate the AutoCAD app from Task Manager But the Select Files window remains. Now the window is freed up for me to select files and drag the window around. Any thoughts as to why this is occurring on my end? Which version of AutoCAD are you using? Do you have multiple AutoCAD sessions open? Quote
GLAVCVS Posted 1 hour ago Posted 1 hour ago 4 hours ago, Paul Li said: @GLAVCVS Thanks for the modified code. But I'm encountering the following errors after attempting to load it: ; error: bad argument type: stringp nil The error is caused by the following lines of code under the PS-EXEC function: ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-TOUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-TOUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) When I change the following lines of code referencing *PS-TOUT* to what you had commented out using *PS-OUT* then at least it'll load successfully: ;|Waiting for a Powershell response / Esperar a que PowerShell responda|; (while (not (findfile *PS-OUT*));(not (findfile *PS-OUT*)) (setq t0 1000) (repeat 1000 (setq t0 (1+ t0))) ) ;|Reading response / Leer respuesta|; (setq fp (open *PS-OUT* "r"));(open *PS-OUT* "r")) (while (setq lin (read-line fp)) (setq result (cons lin result)) ) (close fp) But after this when I call the pl:getfiledps function using the following line of code: (pl:getfiledps "Select Files" (getvar"dwgprefix") "dwg" 1) The Select Files window would appear on top of my AutoCAD session and then just hang there. I'm unable to select any files from this window or move the window out of the way: I would have to terminate the AutoCAD app from Task Manager But the Select Files window remains. Now the window is freed up for me to select files and drag the window around. Any thoughts as to why this is occurring on my end? You were right I forgot to clean *PS-TOUT* from my test code I've also tweaked something else in the code. Try it again Quote
Paul Li Posted 1 hour ago Author Posted 1 hour ago @GLAVCVS BTW: I didn't see any changes to your original code. For example I still see the lines using *PS-TOUT* I've tried it on a couple of Windows 10 Pro OS computers running AutoCAD 2021, 2023 & 2027 one at a time and not multiple sessions. Upon further testing the Select Files window can be unstuck by toggling to the Edge browser making that active and then toggling back to AutoCAD. The problem still occurs even when the Edge browser is not running. But as long as I launch the Edge browser (when it's not already running) then the Select Files window would free up to function as designed. This problem does not occur on the single Windows 11 OS computer I tested this on. Quote
GLAVCVS Posted 50 minutes ago Posted 50 minutes ago 22 minutes ago, Paul Li said: @GLAVCVS BTW: I didn't see any changes to your original code. For example I still see the lines using *PS-TOUT* I've tried it on a couple of Windows 10 Pro OS computers running AutoCAD 2021, 2023 & 2027 one at a time and not multiple sessions. Upon further testing the Select Files window can be unstuck by toggling to the Edge browser making that active and then toggling back to AutoCAD. The problem still occurs even when the Edge browser is not running. But as long as I launch the Edge browser (when it's not already running) then the Select Files window would free up to function as designed. This problem does not occur on the single Windows 11 OS computer I tested this on. It seems that Cadtutor refused to accept my modification. Basically, I changed *TOUT* to *OUT* and '(if (findfile *PS-READY*)' to '(if (and *PS* (findfile *PS-READY*))' Quote
Recommended Posts
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.