本帖最后由 dcl1214 于 2025-9-12 11:40 编辑
为了让更多的lisp同仁可以学习在线更新方法,所以,才分享以下完整代码
温馨提示:
1 你可以将下面的代码放到你的服务器后台的
2 给你的客户只需要几句代码即可
3 如果希望做到vlx实时更新加载,请看我其他帖子(二进制流模式加载)

网友答: 本帖最后由 kozmosovia 于 2025-9-12 10:37 编辑
外部更新EXE的执行关lisp啥事?还能执行完了自动找到运行的CAD并拦截中断用户正在画图的操作,自动启动执行lisp吗?要不能,那和画图时开个播放音乐的EXE有啥区别?有啥lisp技术在里面?
标题是更新lisp软件方法,难不成还需要把lisp编译成exe执行吗?搞笑呢吧
网友答: 要是lisp有异步就好了, 先天不足, 做这个挺累网友答: 本帖最后由 dcl1214 于 2025-9-11 22:32 编辑
支持异步的,看你怎么设计了,比如说,你支持一个wget,或者是curl
查询数据库的文件记录,只需要1秒,接下来交给curl,lisp发布的vlx文件,在cad不关闭的情况下,支持覆盖的,而且还支持不重启cad的情况下二次加载vlx
网友答:
我找了好久都没找到lisp的异步方法,
比如访问网络, 如果网络慢就只能阻塞干等
我倒是看到猫老师用技巧实现假线程, 不知道实际操作咋样.网友答: 本帖最后由 dcl1214 于 2025-9-11 22:47 编辑
curl支持断点续传呀,断点续传的时候,不影响你使用cad的,比如说vlx文件,因为cad的vlx一旦编译成了【独立空间】模式,该vlx是支持一边使用一边更新的
实在不行,就玩流模式的方法,实时加载的,而且没有任何文件痕迹
网友答: 一个面向过程的编程语言能支持异步,怕是对异步有误解网友答: 有时间普及一下服务器的知识
,知识盲区网友答:
很多软件的更新都是一个单独的update.exe在执行的,独立的一个程序网友答: 本帖最后由 dcl1214 于 2025-9-12 11:40 编辑
vlx支持一边更新一遍做图,不影响画图,也不影响更新,两个同时进行的
独立空间支持这种操作
正在画图的程序可以检查自己的vlx是否有字节数变动,如果有,卸载自己,然后更新自己(①可以调用update.vlx,传入参数就卸载了自己,也更新了自己②在线实时二进制流模式加载)
为了让更多的lisp同仁可以学习在线更新方法,所以,才分享以下完整代码
温馨提示:
1 你可以将下面的代码放到你的服务器后台的
2 给你的客户只需要几句代码即可
3 如果希望做到vlx实时更新加载,请看我其他帖子(二进制流模式加载)

- (progn
- (setq config
- (list
- (cons "下载地址"
- "http://大不了大不了大不了点康姆/download_post"
- )
- (cons "查询数据库地址"
- "http://大不了大不了大不了点康姆/select"
- )
- (cons "数据库表名" "zxcadapp")
- (cons "需要独立加载的文件" "cad/run.lsp")
- (cons
- "备注"
- "①如果担心服务器遭洪水攻击可以通过入站规则设定②数据库的表名是随意更换的,你可以给每一个用户配一个表名③如果想限制某一个用户使用软件可以通过ngx设定"
- )
- )
- )
- (defun $pin-jie$
- (strs fgf / a bars len str str str-last strs-car strs-n)
- (if (and strs
- fgf
- (= (type strs) 'list)
- (setq strs (vl-remove nil strs))
- (setq strs-car (CAR strs))
- (= (type strs-car) 'STR)
- (= (type fgf) 'str)
- )
- (progn
- (setq strs (cdr strs))
- (setq strs (reverse strs))
- (setq strs-n nil)
- (while (setq a (car strs))
- (setq strs-n (cons a strs-n))
- (setq strs-n (cons fgf strs-n))
- (setq strs (cdr strs))
- )
- (setq strs-n (cons strs-car strs-n))
- (setq str (vl-catch-all-apply 'apply (list 'strcat strs-n)))
- (if (vl-catch-all-error-p str)
- (progn
- (setq
- strs-n (mapcar
- (function (lambda (a)
- (if (and a (/= (type a) 'str))
- (setq a (vl-prin1-to-string a))
- )
- a
- )
- )
- strs-n
- )
- )
- (setq str (vl-catch-all-apply 'apply (list 'strcat strs-n)))
- (if (vl-catch-all-error-p str)
- (setq str nil)
- )
- )
- )
- )
- )
- str
- )
- (defun $make-file$ (file / a s f)
- (if file
- (progn
- (if (wcmatch file "[,*`/*,]")
- (setq s ($zi-chuan-fen-ge$ file "/"))
- (setq s ($zi-chuan-fen-ge$ file "\\"))
- )
- (setq old "")
- (setq f nil)
- (while (setq a (car s))
- (if f
- (setq f (strcat f "/" a))
- (setq f a)
- )
- (if (findfile f)
- ()
- (vl-mkdir f)
- )
- (setq s (cdr s))
- )
- )
- )
- f
- )
- (defun $zi-chuan-fen-ge$ (str delim / lst i STRS len)
- (if (AND str
- delim
- (= (type str) 'str)
- (= (type delim) 'str)
- (> (strlen delim) 0)
- )
- (progn
- (setq len (strlen delim))
- (while (setq i (vl-string-search delim str))
- (setq lst (cons (substr str 1 i) lst))
- (setq str (substr str (+ 1 len i)))
- )
- (setq lst (cons str lst))
- (setq strs (reverse lst))
- )
- (if str
- (setq strs (list str))
- )
- )
- strs
- )
- (defun $http-server$ (lst / $write-bin-stream$
- array&str content dey err-str
- get&post host hs jg
- jg-read jgs objhttp return-value
- save-p send-zt status str
- value value-text
- )
- (defun $Write-Bin-Stream$ (filename data / ADOStream result xzjg)
- (IF DATA
- (PROGN
- (if (setq ADOStream (vl-catch-all-apply
- 'vlax-create-object
- (list "ADODB.Stream")
- )
- )
- (progn
- (vl-catch-all-apply 'vl-file-delete (list filename))
- (vl-catch-all-apply
- 'vlax-put-property
- (list ADOStream 'type 1)
- )
- (vl-catch-all-apply
- 'vlax-invoke
- (list ADOStream 'open)
- )
- (vl-catch-all-apply
- 'vlax-invoke-method
- (list ADOStream 'write data)
- )
- (setq result (vl-catch-all-apply
- 'vlax-invoke
- (list ADOStream 'savetofile filename 2)
- )
- )
- (if (and ADOStream
- (vlax-method-applicable-p ADOStream 'close)
- )
- (vl-catch-all-apply
- 'vlax-invoke-method
- (list ADOStream 'close)
- )
- (print "stream close error")
- )
- (IF ADOStream
- (vl-catch-all-apply
- 'vlax-release-object
- (list ADOStream)
- )
- )
- (if (vl-catch-all-error-p result)
- (print (vl-catch-all-error-message result))
- (IF (FINDFILE filename)
- (progn
- (if (= (vl-file-size filename) 0)
- (progn
- (vl-catch-all-apply
- 'vl-file-delete
- (list filename)
- )
- (setq xzjg nil)
- )
- (setq xzjg filename)
- )
- )
- )
- )
- )
- )
- )
- )
- xzjg
- )
- (or (setq host (cdr (assoc "IP" lst)))
- (setq host (cdr (assoc "ip" lst)))
- )
- (if (not host)
- (print "没传递ip地址(ip带端口号和方法名)")
- )
- (setq GET&POST "POST")
- (setq content (cdr (assoc "content" lst)))
- (if (not content)
- (print "没传递content")
- )
- (setq array&str (cdr (assoc "返回格式" lst)))
- (or array&str (setq array&str "POST"))
- (setq hs (cdr (assoc "报文头" lst)))
- (setq hs (cons (cons "Client-Auth" (getenv "ComputerName")) hs))
- (setq hs (cons (cons "Response-Charset" "UTF8") hs))
- (and
- host
- (progn
- (SETQ str "")
- (and
- (setq objHttp (vl-catch-all-apply
- (function
- (lambda ()
- (vlax-create-object
- "winhttp.winhttprequest.5.1"
- )
- )
- )
- )
- )
- (PROGN
- (setq return-value nil)
- (if
- (IF (vl-catch-all-error-p
- (SETQ return-value
- (vl-catch-all-apply
- 'vla-open
- (list objHttp GET&POST host 0)
- )
- )
- )
- (progn (print (vl-catch-all-error-message return-value))
- (vlax-release-object objHttp)
- (setq objHttp nil)
- (setq return-value nil)
- nil
- )
- t
- )
- (PROGN
- (if
- (progn
- (mapcar (function (lambda (a)
- (if (and (car a) (cdr a))
- (progn
- (vl-catch-all-apply
- 'vlax-invoke-method
- (list objHttp
- "setRequestHeader"
- (car a)
- (cdr a)
- )
- )
- )
- )
- )
- )
- hs
- )
- (or content (setq content ""))
- (SETQ value
- (vl-catch-all-apply
- 'vlax-invoke-method
- (list objHttp "send" content)
- )
- )
- (if (vl-catch-all-error-p value)
- (progn
- (setq
- err-str (vl-catch-all-error-message value)
- )
- (print err-str)
- (vlax-release-object objHttp)
- (setq objHttp nil)
- (setq send-zt nil)
- )
- (setq send-zt t)
- )
- (setq value nil)
- send-zt
- )
- (PROGN
- (setq dey 1)
- (while (and dey (< dey 50000))
- (cond
- ((and (setq status (vl-catch-all-apply
- 'vlax-get-property
- (list objHttp "status")
- )
- )
- (not (vl-catch-all-error-p status))
- (= status 200)
- )
- (setq dey nil)
- )
- (t (repeat 200))
- )
- (if dey
- (setq dey (1+ dey))
- )
- )
- (if (= status 200)
- (progn
- (if
- (VL-POSITION
- array&str
- (list "sz" "SZ" "数组")
- )
- (progn (setq jg
- (vlax-get-property objHttp 'responsebody)
- )
- (setq value-text nil)
- )
- (PROGN
- (and
- (OR
- (and
- (setq value-text
- (vl-catch-all-apply
- 'vlax-get-property
- (list objHttp 'responseText)
- )
- )
- (not (vl-catch-all-error-p value-text)
- )
- (setq status t)
- )
- )
- (progn (setq jg value-text))
- )
- (IF (vl-catch-all-error-p value-text)
- (SETQ value-text NIL)
- )
- )
- )
- )
- )
- )
- )
- )
- )
- )
- )
- (if objHttp
- (vl-catch-all-error-p
- (vl-catch-all-apply 'vlax-release-object (list objHttp))
- )
- )
- (and jg
- (= (type jg) 'str)
- (setq jg-read (vl-catch-all-apply
- 'read
- (list (STRCAT "(" jg ")"))
- )
- )
- (not (vl-catch-all-error-p jg-read))
- (= (TYPE (car jg-read)) 'LIST)
- (setq jgs jg-read)
- )
- (cond
- ((and
- array&str
- (VL-POSITION array&str (list "点表" "db" "DB"))
- )
- (setq jgs (cdar jg-read))
- )
- ((and
- (= (type jg) 'VARIANT)
- (setq save-p (cdr (assoc "保存路径" lst)))
- )
- (vl-catch-all-apply 'vl-file-delete (list save-p))
- (IF (and (FINDFILE save-p) (vl-filename-extension save-p))
- (print "有同名文件无法删除导致无法保存文件")
- (SETQ JGs ($Write-Bin-Stream$ save-p JG))
- )
- )
- )
- )
- )
- JGs
- )
- (defun $cha-xun-wen-jian$ (ip tbn sql / data)
- (or sql
- (and tbn
- (SETQ SQL
- (strcat
- "SELECT * FROM " tbn
- " WHERE CAST(版本 AS CHAR) = (SELECT CAST(版本 AS CHAR) FROM "
- tbn
- " ORDER BY CASE
- WHEN 版本 REGEXP '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$' THEN
- CAST(SUBSTRING_INDEX(版本, '.', 1) AS UNSIGNED) * 1000000 +
- CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(版本, '.', 2), '.', -1) AS UNSIGNED) * 10000 +
- CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(版本, '.', 3), '.', -1) AS UNSIGNED) * 100 +
- CAST(SUBSTRING_INDEX(版本, '.', -1) AS UNSIGNED)
- WHEN CAST(版本 AS CHAR) REGEXP '^[0-9]+$' THEN
- CAST(版本 AS UNSIGNED)
- ELSE ASCII(SUBSTRING_INDEX(版本, ' ', 1)) * 10000 +
- ASCII(SUBSTRING_INDEX(SUBSTRING_INDEX(版本, ' ', 2), ' ', -1)) * 100 +
- ASCII(SUBSTRING_INDEX(版本, ' ', -1)) END DESC LIMIT 1)")
- )
- )
- )
- (if ip
- (setq
- data ($http-server$
- (list
- (cons "IP" ip)
- (cons "content" sql)
- (cons "返回格式" "DB")
- (CONS "报文头" (list (cons "why" "查询软件包")))
- )
- )
- )
- )
- data
- )
- (DEFUN c:zxcadi
- (config / a ip ip2
- loc-file loc-files n web-file
- wjs zxcad-f zxcadapp
- )
- (SETQ IP (cdr (assoc "下载地址" config)))
- (setq ip2 (cdr (assoc "查询数据库地址" config)))
- (if (not (getenv "zxcad-f"))
- (setenv
- "zxcad-f"
- (strcat (getenv "systemdrive") "\\Changli_harness_software")
- )
- )
- (setq zxcadapp (cdr (assoc "数据库表名" config)))
- (setq zxcad-f (getenv "zxcad-f"))
- (setq zxcad-f (vl-string-translate "\\" "/" zxcad-f))
- (setq wjs ($cha-xun-wen-jian$ ip2 zxcadapp nil))
- (while (setq a (car wjs))
- (setq size-web nil
- size-loc nil
- )
- (setq n (cdr (assoc "名称" a)))
- (setq web-file (cdr (assoc "路径" a)))
- (and (setq size-str (cdr (assoc "字节数" a)))
- (setq size-web (atoi size-str))
- )
- (setq loc-file (cdr (assoc "客户端路径" a)))
- (setq loc-files ($zi-chuan-fen-ge$ loc-file "/"))
- (setq loc-files (vl-remove "{app}" loc-files))
- (setq loc-files (cons zxcad-f loc-files))
- (setq loc-file ($pin-jie$ loc-files "/"))
- (if (findfile loc-file)
- (vl-file-delete loc-file)
- )
- ($make-file$ loc-file)
- (setq loc-file (strcat loc-file "/" n))
- (and loc-file
- (findfile loc-file)
- (setq size-loc (vl-file-size loc-file))
- )
- (if (and size-loc size-web (= size-loc size-web))
- (print (strcat loc-file " 与服务器字节数相等不予下载更新"))
- (progn
- ($http-server$
- (list
- (cons "IP" IP)
- (cons "content" web-file)
- (cons "返回格式" "数组")
- (cons "保存路径" loc-file)
- )
- )
- )
- )
- (PRINT loc-file)
- (setq wjs (cdr wjs))
- )
- (vl-catch-all-apply
- 'load
- (list (findfile (strcat (getenv "zxcad-f") "\\startup.vlx"))
- )
- )
- T
- )
- (IF
- (c:zxcadi config)
- ()
- (PROGN
- (setq web-file (cdr (assoc "需要独立加载的文件" config)))
- (setq
- lsp-f (vl-filename-mktemp
- (STRCAT (GETENV "PUBLIC") "\\run.lsp")
- )
- )
- (if web-file
- ($http-server$
- (list
- (cons "IP" (cdr (assoc "下载地址" config)))
- (cons "content" web-file)
- (cons "返回格式" "数组")
- (cons "保存路径" lsp-f)
- )
- )
- )
- (if (and lsp-f (findfile lsp-f))
- (progn
- (print lsp-f)
- (setq load-zt (vl-catch-all-apply 'load (list lsp-f)))
- (if (vl-catch-all-error-p load-zt)
- (print (strcat "加载: " lsp-f " 失败"))
- )
- )
- )
- (vl-catch-all-apply 'vl-file-delete (list lsp-f))
- )
- )
- (setq ts nil)
- (setq lsp-f nil)
- (setq load-zt nil)
- (setq web-file nil)
- (setq lsp-f nil)
- (setq load-zt nil)
- (setq $pin-jie$ nil)
- (setq $make-file$ nil)
- (setq $zi-chuan-fen-ge$ nil)
- (setq $cha-xun-wen-jian$ nil)
- (setq $http-server$ nil)
- (setq c:zxcadi nil)
- (setq config nil)
- )
网友答: 本帖最后由 kozmosovia 于 2025-9-12 10:37 编辑
dcl1214 发表于 2025-9-12 09:26
很多软件的更新都是一个单独的update.exe在执行的,独立的一个程序
外部更新EXE的执行关lisp啥事?还能执行完了自动找到运行的CAD并拦截中断用户正在画图的操作,自动启动执行lisp吗?要不能,那和画图时开个播放音乐的EXE有啥区别?有啥lisp技术在里面?
标题是更新lisp软件方法,难不成还需要把lisp编译成exe执行吗?搞笑呢吧
网友答: 要是lisp有异步就好了, 先天不足, 做这个挺累网友答: 本帖最后由 dcl1214 于 2025-9-11 22:32 编辑
22693766 发表于 2025-9-11 22:27
要是lisp有异步就好了, 先天不足, 做这个挺累
支持异步的,看你怎么设计了,比如说,你支持一个wget,或者是curl
查询数据库的文件记录,只需要1秒,接下来交给curl,lisp发布的vlx文件,在cad不关闭的情况下,支持覆盖的,而且还支持不重启cad的情况下二次加载vlx
网友答:
dcl1214 发表于 2025-9-11 22:29
支持异步的,看你怎么设计了,比如说,你支持一个wget,或者是curl
查询数据库的文件记录,只需要1秒, ...
我找了好久都没找到lisp的异步方法,
比如访问网络, 如果网络慢就只能阻塞干等
我倒是看到猫老师用技巧实现假线程, 不知道实际操作咋样.网友答: 本帖最后由 dcl1214 于 2025-9-11 22:47 编辑
22693766 发表于 2025-9-11 22:43
我找了好久都没找到lisp的异步方法,
比如访问网络, 如果网络慢就只能阻塞干等
我倒是看到猫老师用技巧 ...
curl支持断点续传呀,断点续传的时候,不影响你使用cad的,比如说vlx文件,因为cad的vlx一旦编译成了【独立空间】模式,该vlx是支持一边使用一边更新的
实在不行,就玩流模式的方法,实时加载的,而且没有任何文件痕迹
网友答: 一个面向过程的编程语言能支持异步,怕是对异步有误解网友答: 有时间普及一下服务器的知识
,知识盲区网友答:
kozmosovia 发表于 2025-9-11 23:03
一个面向过程的编程语言能支持异步,怕是对异步有误解
很多软件的更新都是一个单独的update.exe在执行的,独立的一个程序网友答: 本帖最后由 dcl1214 于 2025-9-12 11:40 编辑
kozmosovia 发表于 2025-9-12 10:33
外部更新EXE的执行关lisp啥事?还能执行完了自动找到运行的CAD并拦截中断用户正在画图的操作,自动启动执 ...
vlx支持一边更新一遍做图,不影响画图,也不影响更新,两个同时进行的
独立空间支持这种操作
正在画图的程序可以检查自己的vlx是否有字节数变动,如果有,卸载自己,然后更新自己(①可以调用update.vlx,传入参数就卸载了自己,也更新了自己②在线实时二进制流模式加载)