转载时请务必保留转载出处和由艾泽拉斯之海洋女神出品的字样;如需刊登,请与作者联系。little_fairycat@126.com.
第三部分:其他
1. 修改显示界面的风格
Installshield 原始安装界面我始终觉得很丑,幸好Installscript 是可以不用写代码就可以改界面风格的。
在 Installation Designer 的左边导航树上找到User Interface | Dialogs
Skins 选项下面显示了不同的界面风格,默认是None,选择一个喜好的风格即可,笔者一般使用Blue 或BlueTC,适用于一般商业软件的稳
重风格;Midnight 比较酷,要是做电脑游戏的安装程序,我一定会选这个风格。
2. 编译打包
一切都准备就绪之后,就差一个编译打包成实际的安装程序的过程了。
编译
编译可以使用工具栏上的 ,检查一下有无定义错误,编译错误等。
打包
打包可以使用工具栏上的 。
1. 第一步,指定一个打包的配置版本,如果使用同一个安装程序源来打包成不同的配置,就可以选择新的配置版本。这里的配置指的
是安装程序本身的配置,包括是否压缩文件、打包成网络安装程序或光盘安装程序、安装程序的客户信息、是否加密等等。
2. 同一配置下允许多个版本的存在;一般笔者习惯于当安装源文件升级的时候,就打包一个新版本出来以示区别,同时也可以保留老
版本的安装程序备用不时之需。
3. 过滤设置,笔者从来没用过。貌似是对feature 的一些设置参数,大概是针对某些版本,如果某些feature 不需要的话,就直接过滤掉
了,安装时候无法选择安装了。不过参数具体怎么设置,包括下面的语言过滤,笔者尚未使用过。但是回想起以前安装的一些大型
软件比如Oracle 之类的,会有一些选项是灰色无法选择安装的,大概就是类似这种功能。
4. 安装程序的语言和被安装的应用程序的语言没有必然联系,因此这里还需要设置一下安装时所用的语言。选择列表里显示的语言取
决于在做安装程序时选择的语言,刚才我们只选择了English,因此这里只显示English 了。如果选择了多项语言,那么在安装时出
现的第一个界面会是让你选择安装时所用语言的界面,非常智能。这种功能针对需要发布到多个语种国家的软件是非常有用的。不
过这样的话,在写脚本的时候,只要是显示在界面上的语言,除了系统可以默认显示的,都要多加一个语言判断,并且显示不同的
内容了。
5. 选择介质类型,一般笔者都会把安装程序刻录到光盘上,因此选择 CD-ROM
6. 光盘选项,第一个选项 Automatic 会自动为你检测所需光盘的规格数量,以及制作出光盘之间的断点。我一般都是选第一项,免去
不少啰嗦事,第二个选项应该是高人才会选的吧。
7. 这个选项指定了打包时的形态:
Compress all files:所有的文件都压缩打包(这里不包括脚本里所写的安装时候从外部拷贝的文件,只包括在Project Assistant 里指定
到各个feature 下的文件)
Leave files uncompressed and separate from the installation package:所有的文件都不打包,以原始形态存在
Custom:定制,允许你指定一部分压缩打包,一部分散放。
笔者喜欢把所有的文件都打包,看上干净并且专业。
8. 对操作系统的要求,一般都默认即可
9. 这个是 Windows 安装引擎,对此没有研究过,凭着上面的解释选了第二个,会帮你打包进安装程序,这样就高枕无忧了。
10. 签名,目前用不到,有兴趣的话可以导入数字签名文件
11. 密码和版权声明。密码还是算了吧,一个商业软件是不该这样设的,客户会骂死的。
12. 是否要包括.NET Framework,Installshield 看来和微软很和谐啊。
13. 编译出来的文件放置的位置,以及一些相关设置,建议长文件名这个选项要选上,以免路径太深造成不必要的问题。
14. 最后一步,显示之前所配置的设置,点击“完成”即可编译出一个安装程序来。
15. 编译好的安装程序文件应该在 工程路径/My Project Name/Product Configuration X/Release X/DiskImages/DISK1 下
点击 setup.exe,就可以安装了。
这里顺便说一下,这个安装程序虽然制作好了,但是如果这样光秃秃地拿给客户,客户是要对产品的印象打折扣的。可以使用 Flash 或者其
他的专业光盘制作软件来制作一个漂亮的应用界面来提供给客户,在插入光盘的时候自动弹出一个漂亮的使用界面,不但印象深刻,而且客
户使用起来也方便。
第四部分:补遗
这篇补遗是《一个完整的安装程序实例—艾泽拉斯之海洋女神出品》的追加叙述,是在这个安装程序安装后发现应用程序运行时的一些小问题,通过安装程序中传递参数和设置环境变量来解决掉问题的,与安装程序本身无关。
这个程序做完之后,工程进入最后的调试阶段;里面发现了两个问题,其实和安装程序本身没有关系,但是都可以通过安装程序来解决,记录在此,以备以后碰到此类问题时可以查阅。
1. JAVA_HOME的问题
之前在第二部分的第九小节里提到了安装完毕后,为JDK设置一个环境变量,事实上这个文档写到这里的时候有一点搞错了先后顺序,因为需要这个环境变量的是第二部分第八小节里安装完毕后需要启动的那个程序,所以后来调试时候发现了,就把第八节的程序内容和第九节的程序内容调换了一下顺序。
但是,很快发现了新问题,在注册表里添加环境变量和在桌面上“我的电脑”里直接添加环境变量是不一样的;注册表里的操作,都需要通过重启动计算机来使之生效,所以矛盾出现了:当这个程序启动的时候,环境变量还没有生效;而如果设置了让计算机重启动,就必须让客户手动启动这个程序,这是非常不友好的操作。
所以这里修改了一下方法,首先把需要启动的程序,也就是一个批处理文件,里面的
set JAVA_HOME=%JAVA_HOME%
这句话改成了
set JAVA_HOME=%1
在批处理里面,需要从外部接收参数的时候,可以把参数写成%1,%2…%n。
然后,在第八小节的程序基础上修改,把
if (LaunchApp (serviceTarget, "") < 0) then
这句话修改成
if (LaunchApp (serviceTarget, javahome) < 0) then
即可。
2. 代码解释
这里javahome就是第九小节里if(RegDBSetKeyValueEx(szKey, "JAVA_HOME", REGDB_STRING, svValue, -1)<0) then这句话里的svValue,即JDK的安装路径。
LaunchApp (serviceTarget, javahome)
不能不佩服IS函数设计者,在这篇文档里,三个地方用到了LaunchApp这个函数,而且每个用法都不同。
参数一:这里写我们要打开的文件,带相对路径的
参数二:cmd_line,这里,我们写入了JDK的路径,这个值将作为参数传递给我们要打开的批处理文件,批处理接收到JDK路径后,便可以正确启动了。
3. Path的问题
这个问题其实和JavaSerive以及操作系统相关;因为在笔者的计算机上一直没有发现这个问题。
在第二部分的第八小节中提到,我们会向Windows安装一个服务,但是笔者在工程用的计算机上始终不能启动这个服务,这次这个调试任务推给了经理,他经过多次试验,发现是环境变量中Path 的问题,只要在Path里添加上JRE的Bin文件路径,这个服务就可以正确启动了。因为没有深入了解JavaSerive的运行机制和Windows服务的运行机制,也没有深究为什么了,猜想可能是这个服务需要找这个路径,而有的操作系统只要指定了JAVA_HOME就可以寻找JRE了,而有的却不行。
闲话休叙,我们需要写一段程序来实现这个功能。
要注意的地方有以下几点:
l Path往往已存在,并且里面有内容,因此不可以像设置JAVA_HOME一样,而要考虑往已有内容中添加JRE路径,并且要考虑内容之间的分号问题
l 要考虑到卸载状态时,不能把Path卸载。说到这个问题,要提一下前面的第九小节,发现引文作者关于卸载时是否卸载自己添加的注册表键值的理解还是不正确的,Help里关于RegDBSetKeyValueEx有这样一句话However, the newly created key is not logged for uninstallation unless it is a subkey of a key already logged for uninstallation.也就是新创建的键值不会被日志记录了要反卸载掉,除非它有子键值被日志记录了要卸载
程序内容仍然添加在OnEnd()里,写在最后,如下:
szKey = "SOFTWARE//JavaSoft//Java Runtime Environment//1.6.0_04";//jre的键
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);//设置一下根键
if (RegDBKeyExist(szKey)=1) then//如果这个键存在
if(RegDBGetKeyValueEx(szKey,"JavaHome",nvType,svValue,nvSize)=0) then //查找这个键的值
javaPath= svValue;
endif;
endif;
**************************************以上为第一部分,以下为第二部分
//wirte the environment variable PATH
szKey = "SYSTEM//CurrentControlSet//Control//Session Manager//Environment"; //环境变量在注册表中所在位置
javaPath=javaPath+"//bin";//jre/bin的路径
if(RegDBGetKeyValueEx(szKey,"Path",nvType,svValue,nvSize)=0)then//如果Path存在
if(svValue!="") then
if(StrFind ( svValue, javaPath )<0) then//如果path还没有jre/bin的路径信息
svValue=svValue+";"+javaPath; //添加路径信息,此时要带上分号
endif;
else
svValue= javaPath;//如果键值为空,则直接添加即可,事实上键值为空的情况不会出现,这句话是无用的判断
endif;
else
svValue= javaPath; //如果没有这个键值,把值也直接添加进去,事实上这个情况也不会出现,因为path在操作系统安装完毕后就存在了,//除非你手动删除了,但是那样操作系统也会有问题了
endif;
if(!MAINTENANCE)then
Disable(LOGGING);
if(RegDBSetKeyValueEx(szKey, "Path", REGDB_STRING_EXPAND, svValue, -1)<0) then//添加或者重设键值
MessageBox ("Path create failed, please set it manually!", SEVERE);
endif;
Enable(LOGGING);
endif;
4. 代码解释
第一部分的目的在于找出JRE的安装路径,所有的函数之前都有解释,不再赘述
第二部分:
szKey = "SYSTEM//CurrentControlSet//Control//Session Manager//Environment";
环境变量,位于注册表的这个位置
*************************************************************************
javaPath=javaPath+"//bin";
需要寻找的是JRE下的bin文件
*************************************************************************
if(RegDBGetKeyValueEx(szKey,"Path",nvType,svValue,nvSize)=0)then
如果Path存在并返回了值。
这里其实如果加上一个判断此键是否存在,代码会更加完善,不过操作系统装完之后这个键是一定存在的,这里笔者偷懒了
*************************************************************************
if(StrFind ( svValue, javaPath )<0) then
判断返回的键值里是否包含jre的bin文件夹的路径
StrFind(szString, strFineMe)
在源字串里查找是否包含指定的字串
参数一: szString,被查找的源字串
参数二:strFineMe,要查找的字串
如果包含要查找的字符串,则返回要查找的字符串在源字符串里的位置;如果查找不到则返回小于0的随机数字
*************************************************************************
if(!MAINTENANCE)then
判断一下安装状态,使之只有在非维护(修改,重新安装,卸载)状态使起作用
*************************************************************************
Disable(LOGGING);
Enable(LOGGING);
这两句话作用分别是停止日志记录和使日志记录重新生效,这是从网上的一篇心得里抄录的,当日志停止记录时候,安装程序就无视了停止日志后的所有操作,这样保证键值不会在反安装时候被操作;其实本来上面一句if(!MAINTENANCE)then(非维护状态时操作)在原文是没有加上去,作者说只要不让日志记录到操作注册表,这个操作就不会被反安装掉,不过好像自己试了一下不行,加上一句,比较保险些,至少试验出来是没问题的。
*************************************************************************
if(RegDBSetKeyValueEx(szKey, "Path", REGDB_STRING_ EXPAND, svValue, -1)<0)
写注册表的键值。
Help里RegDBSetKeyValueEx的对应帮助里有这样一句话If the value data already exists, RegDBSetKeyValueExoverwrites it,也就是,如果键值存在,那么覆盖它。不过对注册表操作后,要把计算机重新启动才能生效;这一点和我们直接在“我的电脑”里操作环境变量是不一样的。
这里,第三个参数改成了REGDB_STRING_ EXPAND,因为在Windows 2003server下,path含有一个%SystemRoot%的相对路径,当时一开始使用了REGDB_STRING,结果无意中发现所有的dos命令都用不了了,在dos下输入path一看,该替换成绝对路径的地方都没有替换掉,当时也是一头雾水,上CSDN一问,有人提醒说我应该看一下IS程序里键值设置时候的类型问题,跑回来一看果然设置有问题,REGDB_STRING是不认识相对路径的,换成REGDB_STRING_ EXPAND就可以了。
5. 文件的只读性问题
用光盘装程序的时候发现一个问题,当从光盘上拷贝出文件的时候,文件会默认为只读格式,导致配置文件不能正常存储数据库信息,因此,在安装程序代码里拷贝完文件后,指定一下文件的属性
SetFileInfo ( szPathFile, nType, nAttribute, szValue );
此处用作SetFileInfo ( szPathFile, FILE_ATTRIBUTE, FILE_ATTR_NORMAL, "" );