跳到主要內容
Hai 二次開發工作室

AutoCAD

AutoLISP 跑不動?錯誤訊息對照與 7 個排查方向

從網路下載或自己寫的 LISP,載入後沒反應、畫出來的位置不對,或指令行跳出看不懂的 error 訊息? 先用第一節的對照表依錯誤訊息找原因,再看後面 7 個排查方向,每一項都附上檢查方式。

內容依 Autodesk AutoCAD 2025 的說明整理;AutoLISP 參考與錯誤處理的部分只有英文版說明,錯誤訊息照原文列出。

本文目錄(9 節)

先看錯誤訊息:對照表

指令行訊息(關鍵字)意思先檢查
bad argument type: lselsetp nil函式要的是選取集,拿到的是 nilssget 有沒有選到物件(見第 4 節)
bad argument type: stringp 1函式要的是字串,拿到的是數字 1(說明的例子是 strcat 拿到數字)傳進去的值是什麼型別,可以先用 type 函式檢查
bad argument type: 2D/3D point函式要的是點座標,拿到的不是點座標有沒有取到、串列有沒有寫錯
too few arguments給的引數不夠自訂函數有幾個引數,呼叫時就要給幾個值
no function definition: VLAX-…函式沒有定義有沒有先執行 (vl-load-com)、相依的 LISP 檔有沒有一起載入(見第 5 節)
no function definition: ACET-…用到 Express Tools 的函式,但沒有載入輸入 EXPRESSTOOLS 啟用 Express Tools;AutoCAD 2025 起程式必須先呼叫acet-load-expresstools(只有 AutoCAD for Windows 有)

同一個運算式有兩個錯誤時,先報哪一個不一定。說明舉的例子是 (inters 'a): 引數太少、型別也不對,所以可能出現 too few arguments,也可能出現 bad argument type: 2D/3D point,程式兩種都要能處理。

1. 載入時被擋下:可信任的位置

從 AutoCAD 2014 起,程式能從哪些資料夾載入,受 SECURELOAD 系統變數限制。 LISP 檔不在「可信任的位置」時,AutoCAD 會跳出安全性警告;若 SECURELOAD 設為 2,則會直接不載入。

檢查方式

  • 在指令行輸入 SECURELOAD,看目前的值(0 不限制、1 警告、2 只載入可信任的位置)
  • 到「選項」→「檔案」→「可信任的位置」,把放 LISP 的資料夾加進去
  • 公司電腦若由 CAD 管理員統一設定,SECURELOAD、TRUSTEDPATHS、LEGACYCODESEARCH可能已經被鎖住(Autodesk 說明的做法是用 CAD 管理員控制公用程式鎖定),自己改不動時請管理員調整
  • LISP 放在哪裡、怎麼加入啟動套件或 acaddoc.lsp,見AutoCAD LISP 怎麼用?

建議把公司共用的 LISP 集中放在一個資料夾,統一加入可信任的位置,不要散落在各人桌面。

2. 畫出來的位置不對:物件鎖點干擾

程式用 command 呼叫指令並傳入座標時,如果常駐式物件鎖點(OSMODE)是開著的, 點位可能被鎖到附近物件的端點、中點等位置,畫出來的圖就偏掉了。這種錯誤不會有錯誤訊息,不容易察覺。

改法

OSMODE 的說明提到,撰寫自訂常式時可以用 16384 位元碼暫時抑制常駐式物件鎖點, 不會破壞原本的設定。執行前先記下 OSMODE,加上 16384,結束時再還原:

(defun c:DrawBox (/ oldOsmode)
  (setq oldOsmode (getvar "OSMODE"))
  (setvar "OSMODE" (logior oldOsmode 16384))
  (command "_.RECTANG" '(0 0) '(100 50))
  (setvar "OSMODE" oldOsmode)
  (princ)
)

要注意:程式中途出錯時,後面的還原不會被執行。完整的做法還要搭配使用者可以自訂的錯誤處理函式 *error*; 說明提到,AutoLISP 的錯誤處理可以在出錯時把 AutoCAD 的環境還原到已知的狀態。

3. 指令選項沒反應:語系版本差異

在非英文版的 AutoCAD 中,指令名稱和選項可能是當地語言。Autodesk 說明舉的例子是: 沒加底線時,法文版會預期指令名稱是 CERCLE,程式裡寫 circle 就認不得。

在指令與選項前加上底線 _,會使用英文的原始名稱,同一行程式在不同語言版本都能用; 指令前再加上句點 .,則會使用標準指令,而不是被 AutoLISP 重新定義過的指令:

(command "_.ZOOM" "_Extents")

4. bad argument type:選取集是 nil

; error: bad argument type: lselsetp nil

意思是某個函式預期拿到選取集,實際上拿到的是 nil。ssget 沒有選到任何物件時會傳回 nil(例如使用者直接按 Enter,或篩選條件寫錯), 後面卻直接拿去用 sslength、ssname,就會出現這個錯誤。

改法

(if (setq ss (ssget '((0 . "INSERT"))))
  (progn
    ;; 有選到圖塊才處理
    (princ (strcat "\n選到 " (itoa (sslength ss)) " 個圖塊"))
  )
  (princ "\n沒有選到圖塊。")
)

同樣的道理適用於 entsel、getpoint 等所有可能回傳 nil 的函式。

5. no function definition:函式沒有載入

; error: no function definition: VLAX-ENAME->VLA-OBJECT

表示程式呼叫了一個目前沒有被定義的函式,可能的原因有:

  • 缺少 (vl-load-com):說明寫明使用 vlax- 開頭的 AutoLISP 延伸函式前,必須先執行這一行; 它也會初始化 AutoLISP 的 ActiveX 支援(vla- 開頭的函式)
  • 函式在另一個檔案:程式呼叫了共用函式庫裡的函式,但那個 LISP 檔沒有一起載入。 共用函式庫可以寫進 acaddoc.lsp 一起載入,做法見公司統一設定:acaddoc.lsp
  • 用到 Express Tools 的 acet- 函式:Express Tools 沒有啟用時就找不到這些函式,處理方式見上面的對照表
  • 拼錯字或產品不支援:例如在 AutoCAD LT 使用了不支援的函式(詳見AutoCAD LT 能用 LISP 嗎?)

6. 時好時壞:變數沒有區域化

defun 的參數列中,斜線 / 後面列出的是區域變數。 說明的用意是讓函式裡的變數不受其他自訂函式與應用程式影響;沒有列進去的變數都是全域變數, 可能被其他 LISP 程式讀到或覆蓋,造成「單獨執行正常、跟其他程式一起用就出錯」。

;; 不建議:ss、i 都是全域變數
(defun c:CountBlk () ...)

;; 建議:把用到的變數列在 / 後面
(defun c:CountBlk (/ ss i) ...)

7. 中文變亂碼:檔案編碼與 LISPSYS

提示文字或圖層名稱裡的中文變成亂碼時,先檢查 LSP 檔的存檔編碼和 AutoCAD 版本。 AutoCAD 2020 和更早的版本,LSP 原始檔只支援 ASCII;從 AutoCAD 2021 起,可以存成 ASCII 或 Unicode。 2021 之後的行為由 LISPSYS 系統變數決定:

LISPSYSAutoLISP 函數與 Unicode預設編輯器編譯時的字元集
0不完全支援(等於 AutoCAD 2020 和更早版本的行為,只有 Windows 版)Visual LISP IDEASCII (MBCS)
1(初始值)完全支援Visual Studio CodeUnicode
2完全支援Visual Studio CodeASCII (MBCS)

檢查方式

  • 用文字編輯器確認檔案目前存成什麼編碼
  • 在指令行輸入 LISPSYS 看目前的值;改了 LISPSYS 要重新啟動 AutoCAD 才生效
  • 同一份檔案要給 2020 以前的版本用時,存成 ASCII,並在那個版本上實際測試

怎麼找到錯在哪一行

  • 在關鍵位置印出變數:用 (princ var) 確認每一步拿到的值是否符合預期,AutoCAD LT 上也能用
  • 使用除錯工具逐步執行:在完整版 AutoCAD 輸入 VLISP。LISPSYS 為 1 或 2 時開啟 Visual Studio Code, 搭配「AutoCAD AutoLISP 延伸」設定中斷點;設為 0 時開啟的是 Visual LISP (VL) IDE。 AutoCAD LT 沒有 VL IDE,也不支援用 VS Code 的 AutoLISP 延伸除錯
  • 縮小範圍:把程式拆成小段分別測試,先確認選取、再確認計算、最後才執行修改圖面的部分

參考資料(Autodesk AutoCAD 2025 說明):About Error Handling(英文)、About Functions with Arguments(英文)、About Local and Global Variables(英文)、ssget(英文)、AutoLISP Extensions Reference(英文)、What's New or Changed with AutoLISP(英文)、OSMODE (系統變數)、LISPSYS (系統變數)、VLISP (指令)、關於載入 AutoLISP 應用程式、關於安全性及病毒防護、使用 Express Tools、關於 AutoLISP 相容性、AutoLISP (AutoCAD LT 2024)

常見問題

Q:LISP 載入後輸入指令沒有反應,要先檢查什麼?

先看指令行有沒有錯誤訊息,再確認檔案是否真的載入成功(APPLOAD 載入後指令行會顯示結果),以及指令名稱是否和程式裡 defun c: 後面的名稱一致。

Q:bad argument type: lselsetp nil 是什麼意思?

函式預期拿到選取集,實際拿到的是 nil。ssget 沒有選到任何物件時會傳回 nil,後面直接拿去給 sslength、ssname 就會出現這個錯誤。用 (if (setq ss (ssget ...)) ...) 先判斷有沒有選到,再往下處理。

Q:出現 no function definition: ACET- 開頭的函式怎麼辦?

ACET- 開頭的是 Express Tools 的函式。完整版 AutoCAD 預設安裝就包含 Express Tools,在指令行輸入 EXPRESSTOOLS 啟用;AutoCAD 2025 起,用到 Express Tools 公用程式函式的程式,必須先呼叫 acet-load-expresstools 初始化這些函式(只有 AutoCAD for Windows 有)。

Q:同一個 LISP 在同事電腦可以用,我的不行,可能是什麼原因?

可能是 AutoCAD 版本或語系不同、可信任的位置設定不同、物件鎖點與系統變數設定不同,或同事的電腦另外載入了程式需要的其他 LISP 檔(包括 Express Tools)。

LINE諮詢開發需求