秋枫 发表于 2005-5-20 22:49:00

[原创]AutoLISP程序的安装制作教程(三)

本帖最后由 作者 于 2005-5-22 11:00:10 编辑 <br /><br /> 这两天更新了我的安装程序制作向导,添加了对已有安装包的维护功能与卸载时菜单的卸载支持。另对样例的加载LISP程序进行了优化。因此,决定写一篇新的教程。



这里,以周海兵朋友制作的文字修改大师9.0为一个样例,为它在AutoCAD2000以上的版本制作一个安装程序。(他的文字修改大师目前最新的版本已经挺高了,这里不管,以这个旧为例说明问题。)


文字修改大师(For AutoCAD 2000以上的版本)主要文件有:<BR>ctt.vlx - 主程序<BR>ctt.mns - 菜单文件<BR>ctt.dll - 资源文件<BR>license.rtf - 授权协议<BR>readme.txt - 程序简介,信息<BR>文字修改大师.chm - 帮助文件


因为AutoCAD 2002与AutoCAD 2004的菜单文件编译后的MNC文件格式不一样,2004与2006也不同,为了保证它的菜单可以同时在各个版本的AutoCAD中使用,这里把文件ctt.mns与ctt.dll复制了两份,分别起名为ctt2004.mns, ctt2004.dll与ctt2006.mns, ctt2006.dll。


所有文件准备好后,复制到一个文件夹中,例如D:\文字修改大师。如图:


http://quelea.w3.zccn.net/attachments/month_0505/20205420liao_SNAG26.png


下面开始编写初始化LISP程序。这里,我们创建一个LISP程序,命名为:LoadCtt.lsp,这个程序将负责把菜单、主程序等加载到系统中。


以下是这个LoadCtt.lsp的写法。我尽量在注释中解释:


<BR>;; 首先定义初始化函数<BR>(defun InitCttApplication (/<BR>                                                                                                                                                                                                               ;; 内部函数<BR>                                                                                                                                                                                                               GetMyApplicationPath GetCttPath<BR>                                                                                                                                                                                                               strParse                                                                                               StrUnParse<BR>                                                                                                                                                                                                               Ctt_AddSupportPath               Load_CttMenu<BR>                                                                                                                                                                                                               ctt_placemenu<BR>                                                                                                                                                                                                               ;; 局部变量<BR>                                                                                                                                                                                                               Ctt_cmdecho_save<BR>                                                                                                                                                                                                       )


;;; 取得本程序的路径.<BR>;;; 文件路径从注册表中读取,这些信息由安装程序负责写入注册表<BR>;;; ---------------------------------------------------------------------------------<BR>       (defun GetMyApplicationPath (AppID)<BR>                       (vl-registry-read<BR>                                       (strcat<BR>                                                       "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"<BR>                                                       AppID<BR>                                                       "_is1"<BR>                                       )<BR>                                       "Inno Setup: App Path"<BR>                       )<BR>       )


        ;; 这里取得安装后,安装的文件夹的绝对路径<BR>        ;; 注意:这里的AppID为"文字修改大师", 稍后的安装程序制作向导设置中必须与这里保持一致<BR>       (defun GetCttPath ()<BR>                       (GetMyApplicationPath "文字修改大师")<BR>       )


;;; 解析字符串为表(函数来自明经通道转载)<BR>;;; ---------------------------------------------------------------------------------<BR>       (defun strParse (Str Delimiter / SearchStr StringLen return n char)<BR>                       (setq SearchStr Str)<BR>                       (setq StringLen (strlen SearchStr))<BR>                       (setq return '())<BR>                       (while (&gt; StringLen 0)<BR>                                       (setq n 1)<BR>                                       (setq char (substr SearchStr 1 1))<BR>                                       (while (and (/= char Delimiter) (/= char ""))<BR>                                                       (setq n (1+ n))<BR>                                                       (setq char (substr SearchStr n 1))<BR>                                       ) ;_ end of while<BR>                                       (setq return (cons (substr SearchStr 1 (1- n)) return))<BR>                                       (setq SearchStr (substr SearchStr (1+ n) StringLen))<BR>                                       (setq StringLen (strlen SearchStr))<BR>                       ) ;_ end of while<BR>                       (reverse return)<BR>       ) ;_ end of defun


;;; 反解析表为字符串(函数来自明经通道转载)<BR>;;; ---------------------------------------------------------------------------------<BR>       (defun StrUnParse (Lst Delimiter / return)<BR>                       (setq return "")<BR>                       (foreach str Lst<BR>                                       (setq return (strcat return Delimiter str))<BR>                       ) ;_ end of foreach<BR>                       (substr return 2)<BR>       ) ;_ end of defun


;;; 添加支持文件搜索路径<BR>;;; ---------------------------------------------------------------------------------<BR>;;; note:       第二个参数如果为真, 插最前,否则插最后<BR>;;;                                                       <BR>       (defun Ctt_AddSupportPath (PathToAdd isFirst / supportlist)<BR>                       (if (not<BR>                                                                       (vl-string-search<BR>                                                                                       (strcase (strcat pathToAdd ";"))<BR>                                                                                       (strcase (strcat (getenv "ACAD") ";"))<BR>                                                                       )<BR>                                                       )                                                                                                                                                                                                                                               ; 保证不重复添加<BR>                                       (progn<BR>                                                       (setq supportlist (strparse (getenv "ACAD") ";"))<BR>                                                       (setq supportlist<BR>                                                                                                               (vl-remove-if-not<BR>                                                                                                                               'vl-file-directory-p<BR>                                                                                                                               supportlist<BR>                                                                                                               )<BR>                                                       )                                                                                                                                                                                                                                               ; 移除不存在的文件夹<BR>                                                       (if isFirst<BR>                                                                       (setq supportlist (cons PathToAdd supportlist))<BR>                                                                       (setq supportlist (append supportlist (list PathToAdd)))<BR>                                                       )<BR>                                                       (setenv "ACAD" (strUnParse supportlist ";"))<BR>                                       )<BR>                       )<BR>       )


       ;; 根据不同的AutoCAD版本加载不同的菜单文件。<BR>       (defun Load_CttMenu (/ acadver)<BR>                       (setq acadver (atof (getvar "acadver")))<BR>                       (cond<BR>                                       ((and (&gt;= acadver 15.0) (&lt; acadver 16.0))<BR>                                               (command "_menuload" "ctt.mns")<BR>                                       )<BR>                                       ((and (&gt;= acadver 16.0) (&lt;= acadver 16.1))<BR>                                               (command "_menuload" "ctt2004.mns")<BR>                                       )<BR>                                       ((&gt;= acadver 16.2) (command "_menuload" "ctt2006.mns"))<BR>                       )<BR>       )


       ;; 这个函数用来插入菜单条<BR>       ;; The following code "placemenu" from LUCAS(龙龙仔)<BR>       (defun ctt_placemenu (/ n)<BR>                       (if (menugroup "CTT")<BR>                                       (progn<BR>                                                       (setq n 1)<BR>                                                       (while (&lt; n 24)<BR>                                                                       (if (menucmd (strcat "P" (itoa n) ".1=?"))<BR>                                                                                       (setq n (+ n 1))<BR>                                                                                       (progn<BR>                                                                                                       (if (&gt; n 3)<BR>                                                                                                                       (setq n (- n 2))<BR>                                                                                                                       (setq n 3)<BR>                                                                                                       )                                                                                                                                                                                               ;if<BR>                                                                                                       ;; 如需插入多条菜单,以反序在这里写:<BR>                                                                                                       ;; 因只有一条下拉菜单,因此这里4,3,2条注释掉<BR>                                                                                                       ;; (menucmd (strcat "p" (itoa n) "=+CTT.pop4"))<BR>                                                                                                       ;; (menucmd (strcat "p" (itoa n) "=+CTT.pop3"))<BR>                                                                                                       ;; (menucmd (strcat "p" (itoa n) "=+CTT.pop2"))<BR>                                                                                                               (menucmd (strcat "p" (itoa n) "=+CTT.pop1"))<BR>                                                                                                       (setq n 25)<BR>                                                                                       )                                                                                                                                                                                                               ;progn<BR>                                                                       )                                                                                                                                                                                                                               ;if<BR>                                                       )                                                                                                                                                                                                                                               ;while<BR>                                       )                                                                                                                                                                                                                                                               ;progn<BR>                       )                                                                                                                                                                                                                                                                               ;if<BR>                       (princ)<BR>       )


;;; -----------------------------------------------------<BR>;;; main:<BR>;;; -----------------------------------------------------<BR>       (setq Ctt_cmdecho_save (getvar "cmdecho"))<BR>       (setvar "cmdecho" 0)


       ;;        添加支持路径。这里只添加一条。多条的话自行修改。<BR>       (Ctt_AddSupportPath (GetCttPath) nil)


       ;; 如果菜单组还没有被加载,则加载之<BR>       (if (not (menugroup "Ctt"))<BR>                       (Load_CttMenu)<BR>       )


       ;; 插到合适的位置<BR>       (ctt_placemenu)<BR>       (setvar "cmdecho" Ctt_cmdecho_save)<BR>       (setq Ctt_cmdecho_save nil)


       (princ)<BR>) ;_end of defun initCttApplication


(initCttApplication)


;; 加载主程序<BR>;; 为节省内存,这里也可以以autoload函数形式定义<BR>;; 有几条写几条<BR>(load "ctt.vlx")


(princ)


至此,所有的要添加支持路径、添加菜单的工作在LISP中都做好了。下面运行本人制作的安装程序制作向导:


http://quelea.w3.zccn.net/attachments/month_0505/20210803fc5j_SNAG01.png


设置一些基本的信息:


http://quelea.w3.zccn.net/attachments/month_0505/20210845zwo4_SNAG02.png


设置AppID。注意:这里必须与LoadCtt.lsp中的GetCttPath一致。AppID设置不正确将导致LoadCtt.lsp无法确定本程序的安装的位置。


http://quelea.w3.zccn.net/attachments/month_0505/20211046wtlz_SNAG03.png


下面是一些常规设置了。<BR>告诉安装程序,这个程序支持的AutoCAD版本:<BR>AutoCAD 2000/2000i/2002: R15.0~R15.1<BR>AutoCAD 2004: R16.0<BR>AutoCAD 2005: R16.1<BR>AutoCAD 2006: R16.2


http://quelea.w3.zccn.net/attachments/month_0505/2021133641s7_SNAG04.png


指定我们的程序文件。早准好了:


http://quelea.w3.zccn.net/attachments/month_0505/2021140852t8_SNAG05.png


指定启动AutoCAD时的初始化程序:


http://quelea.w3.zccn.net/attachments/month_0505/20211613a8zd_SNAG06.png


指定默认的安装文件夹:


http://quelea.w3.zccn.net/attachments/month_0505/20211711oles_SNAG07.png


指定开始菜单的程序组。与上一版程序不同的是,我作了小小的修改,即允许不创建开始菜单中的程序组。卸载程序时可以到控制面板的添加、删除程序中卸载。


http://quelea.w3.zccn.net/attachments/month_0505/2021191407yc_SNAG08.png


http://quelea.w3.zccn.net/attachments/month_0505/20212058eb5i_SNAG09.png<BR>http://quelea.w3.zccn.net/attachments/month_0505/20212106kh0n_SNAG10.png<BR>http://quelea.w3.zccn.net/attachments/month_0505/20212112b91e_SNAG11.png<BR>http://quelea.w3.zccn.net/attachments/month_0505/20212124b91e_SNAG12.png


这里告诉安装程序在卸载时是不是要卸载菜单组。这个也是新添加的功能。在AutoCAD 2005及以前的版本中,菜单组如果找不到系统会提示出错信息。这里卸载程序用于从注册表中清除菜单组信息以免用户卸载后AutoCAD提示出错。对于AutoCAD 2006以上的版本,经试验无此必要了。


考虑到这个文字修改大师也支持AutoCAD 2000-2005的版本,因此这里填入卸载时要卸载的MenuGroup名称为ctt. (MenuGroup的名称在mnu或mns文件中定义)。


注意:LoadCtt.lsp同时也向AutoCAD系统中添加了支持搜索路径,卸载程序卸载时会自动把本程序路径以及本程序路径的子路径从AutoCAD系统的搜索路径中去除,无需设置。


http://quelea.w3.zccn.net/attachments/month_0505/2021281052u9_SNAG13.png


完成。


http://quelea.w3.zccn.net/attachments/month_0505/202128391xp4_SNAG14.png<BR>http://quelea.w3.zccn.net/attachments/month_0505/20212853kh0n_SNAG15.png


安装包生成完毕:


http://quelea.w3.zccn.net/attachments/month_0505/20212927if8l_SNAG16.png


看看生成的安装程序,试运行之(全程截图):


http://quelea.w3.zccn.net/attachments/month_0505/20213123a8zd_Panorama.png


如何修改已经做好的安装程序?可以用WinRAR或7z解压之。这次安装向导修订中我我在基本信息页也添加了一个维护的功能按钮,如图所示:


http://quelea.w3.zccn.net/attachments/month_0505/202134041xp4_SNAG27.png


解开setup.exe后,你可以手动编辑其中的setup.ini或DATA文件夹中的其它文件。Setup.ini内容很简单明了,我也不多说了:<BR><BR><BR>AppID=文字修改大师<BR>AppName=文字修改大师<BR>AppVerName=文字修改大师 V9.0<BR>LISPStartup=loadctt.lsp<BR>DefaultPath=文字修改大师<BR>DefaultGroup=文字修改大师<BR>License=License.rtf<BR>Help=文字修改大师.chm<BR>Info=ReadMe.txt<BR>VersionSupport=R15.0;R15.1;R16.0;R16.1;R16.2<BR><BR>WizardImageFile=<BR>WizardSmallImageFile=<BR><BR>RemoveMenuGroup=ctt


重建安装包也可以用这个维护功能实现。


相关链接:<BR>        ● AutoLISP程序的安装制教程(二)<BR>        ● AutoLISP程序的安装制教程(一)<BR>        ● AutoCAD二次开发程序的安装制作向导<BR>        ● Inno Setup<BR>        ● 7-zip


<BR>        <BR>

angel066499 发表于 2020-2-10 23:06:06

能解决一下现在2010以下版,启动组中没有植入的vlx,是什么原因呢?

wmh-3816 发表于 2022-9-17 23:04:37

学习,谢谢分享

LIULISHENG 发表于 2020-2-16 23:01:42

学习了学习了

spring 发表于 2005-5-21 11:18:00

谢谢秋枫的程序


我们又得更新一次了,呵呵.

BDYCAD 发表于 2005-5-21 15:42:00

BDYCAD 发表于 2005-5-21 15:51:00

我在这步指定加载ACAD.LSP, 可是安装后启动CAD没有加载到哦. 原因是安装后没有自动加上支持路径.



spring 发表于 2005-5-21 17:06:00

我的没有问题


安装只是把文件复制到指定的目录并加载你所指定的LISP,其它添加路径等动作是在你所指定的LISP里面完成的

xj841000 发表于 2005-5-21 17:56:00

试一试

BDYCAD 发表于 2005-5-21 17:58:00

明白了. 不好意思啊. 我还没有看前面的LISP程序.

秋枫 发表于 2005-5-22 10:49:00

以下是引用BDYCAD在2005-5-21 15:42:38的发言:
因为在vlisp中控制加载支持路径可以有更多的灵活性。你自己可以根据需要决定是否添加,是添加一条还是多条。一般来说如果是只有一个vlx文件的应用程序就没有必要添加支持路径了。添加了支持路径会增加整个环境变量ACAD的总长度。太长的支持路径会导致有些操作这个变量的应用程序字符串溢出。我有一阵子用理正建筑软件就发现了这个问题,因为我添加了五六条支持路径,超出了256个字符,导致它的ARX在启动时就出错。出错的原因是很久以后才找到的,跟作者联系后才修正了这个错误。这种事情尽管责任不在我方,但能尽量避免还是避免。

秋枫 发表于 2005-5-22 10:51:00

BDYCAD发表于2005-5-21 17:58:00static/image/common/back.gif明白了. 不好意思啊. 我还没有看前面的LISP程序.


<BR>这回我的示例LISP代码比上次的示例稍作了改进,防止了一些多余的重复操作,提高了一点效率。供参考。


具体怎么写还是看你了,呵呵。

kevinchan 发表于 2005-5-25 09:24:00

有个小小的提议,能否增加安装程序名(setup.exe)的自定义图标?
页: [1] 2 3
查看完整版本: [原创]AutoLISP程序的安装制作教程(三)