论坛风格切换切换到宽版
  • 6648阅读
  • 13回复

Setup Factory 9 安装工厂的个人见解 [复制链接]

上一主题 下一主题
离线cdj68765
 

发帖
5
金钱
50
威望
5
只看楼主 倒序阅读 0 发表于: 2015-03-26

背景音乐篇




最近几天,在忙一个游戏汉化补丁的的时候,用到了这个用来制作安装程序的软件,并且学到了不少的东西,在此来分享一下经验吧
首先关于这个软件基础的东西,我就不讲了,感兴趣的或者不懂的,可以下载这个看下http://www.hanzify.org/UserFiles/File/How_use_SF.rar
我相信这位大大写的基础教程外加跟帖回复里面 都讲的很清楚了,虽然是基于Setup Factory 7的,但是大致上都一样


那么在有上面那个教程的基础下,我又要讲什么呢,其实啊,在我对照上面那个教程进行安装包制作的时候,也遇到了不少麻烦,在不断失败了百来此之后,才做出了成品,因此,这篇教程是在上面那个教程的基础下,根据我所遇到的问题,以及安装流程,一步步详细的讲,分享我所遇到的问题以及各种注意事项吧,好了,废话不多说开始吧。
首先,这个安装包,在打开的时候,需要自动播放背景音乐
为了实现这个功能,需要先转换音乐文件为wav格式,然后点击资源,初始文件,然后点添加把音乐添加进去

这样一来,音乐就相当于保存到了安装包的临时文件夹里面,临时文件夹的变量是%TempLaunchFolder%
这个变量很重要所以加红色字体
添加了文件以后,我们需要让音乐播放。


我们在安装之前的开始安装选项里面的操作选项卡中的第一个选项卡(预加载选项卡)里面键入以下代码


function PlayWAV(strWAVFile,bLoop)
local nFlags = 11;
local strArgs = "\""..strWAVFile.."\","..nFlags;
DLL.CallFunction("winmm.dll","sndPlaySoundA",strArgs,DLL_RETURN_TYPE_LONG,DLL_CALL_STDCALL);
end
PlayWAV(SessionVar.Expand("%TempLaunchFolder%\\music.wav"));


nFlags = 11表示设置播放为循环播放,如果改为1就是正常播放,其他的地方不需要改动,这段代码是从Setup Factory的用户帮助里面照抄下来的,并且做了一些修改,其中


PlayWAV(SessionVar.Expand("%TempLaunchFolder%\\music.wav"))


这句话,PlayWAV()是调用上面写的函数这个不用讲,SessionVar.Expand()是从变量返回字符串,注意,Lua脚本里面的函数,要对变量进行操作,都需要用到SessionVar.函数系列,也就是说,直接打PlayWAV("%TempLaunchFolder%\\music.wav")是不可行的,必须要通过SessionVar.Expand函数来从变量返回字符串才能用,因此SessionVar.函数系列是常用的函数。
%TempLaunchFolder%\\music.wav就没啥好说的了,%TempLaunchFolder%就是打开安装包后生成的临时路径,后面跟着音乐文件,这样就组成了临时音乐路径,在安装完毕以后会自动删除。
至此打开安装包后自动播放音乐的功能已经实现了。

离线cdj68765

发帖
5
金钱
50
威望
5
只看该作者 1 发表于: 2015-03-26
从注册表自动获得安装路径篇

好了,安装程序运行后背景音乐开始播放了,我们点下一步,看到了用户协议,以及再下一步的选择安装目录,因为这两个有所关联,所以一起讲。
首先将选择安装目录的事情吧。
首先,我做的这个是补丁安装包,既然是补丁安装包,也就是对源程序进行修补,安装的时候,自然希望直接定位到源程序,而不需要用户手动去选择目录这么麻烦,虽然选好和主程序一样的默认目录也是一个办法,不过个人觉得还不够。
考虑到所有程序安装的时候,都会在注册表里面生成一个注册文件,在注册信息里面,我确实看到了输入有源程序的安装目录的键,我觉得只要取这个键的数据,然后自动输入到安装路径里面去就行了,于是我写了以下代码






path = Registry.GetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\XX\\XX", "InstTo", false)
SessionVar.Set("%AppFolder%", path);
讲一下,Registry.GetValue函数是,在注册表的设定位置,从该位置的指定键里面获得数据
然后我将获得的数据返回给了path变量(这个Lua脚本莫非使用变量不需要预先定义么?好像想用什么变量就用什么,真方便)
然后我们需要将这个变量里面的数据传送给默认的安装目录,还记得我在上一讲所讲过的吧,涉及到参数的改变都需要使用SessionVar.函数系列,这里就用到了SessionVar.Set函数,作用是将%AppFolder%参数里面的数据设置成path里面的数据,
而如果你要问为什么%AppFolder%就是默认安装目录,我只能说,请认真看基础教程。
这样一来,就实现了从注册表的这个位置返回了地址给了默认安装目录的功能。


然后我发现,从这个地址不一定能返回正确的路径,因为源程序的安装程序,在某种情况下面,可能不会在这个地址写入安装地址,那怎么办?于是我想到了,只要安装了程序,就一定会产生删除文件,而删除文件的路径也会写到注册表里面,那我能不能利用这个删除文件的路径,获得安装地址呢?答案是可行的,于是我写了下面的代码
我能不能利用这个删除文件的路径,获得安装地址呢?答案是可行的,于是我写了下面的代码

path3 = Registry.GetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MajiroApp暁の護衛~罪深き終末論~", "UninstallString", false)
path3 = String.TrimRight(path3, "UnInst.exe");
SessionVar.Set("%AppFolder%", path3);
第一句话不解释了,就是获得删除文件的地址
但是既然是删除地址,那么必然指向的是一个删除文件(X:\xx.exe),但是我们想要得到的是单纯的路径(X:\),那该怎么办呢,其实只要把后面的字符给删掉就可以了
String.TrimRight函数的功能便是,从指定变量的字符串右边开始,删除指定的字符串,然后返回
得到我们想要的字符串后,我们把变量里面的数据传送给了默认安装路径参数"%AppFolder%"
这样从注册表的删除文件路径获得程序安装路径的功能实现了
在此我贴一下全部的代码



if(SessionVar.Expand("%AppFolder%") == "")then
path = Registry.GetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\しゃんぐりら\\暁の護衛~罪深き終末論~", "InstTo", false)
SessionVar.Set("%AppFolder%", path);
if(SessionVar.Expand("%AppFolder%") == "")then
path2 = Registry.GetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MajiroApp嬇偺岇塹乣嵾怺偒廔枛榑乣", "UninstallString", false)
path2 = String.TrimRight(path2, "UnInst.exe");
SessionVar.Set("%AppFolder%", path2);
if(SessionVar.Expand("%AppFolder%") == "")then
path3 = Registry.GetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MajiroApp暁の護衛~罪深き終末論~", "UninstallString", false)
path3 = String.TrimRight(path3, "UnInst.exe");
SessionVar.Set("%AppFolder%", path3);
end
end
end
可以看到代码中有If()then这种条件指令,功能就是用来,分辨上一条地址有木有获得,获得了就跳过,没有获得就从if里面的语句获得
然后这里有一个问题需要注意,就是这段代码贴在哪里的问题


我们会想当然以为,既然是读取注册表的地址给默认安装目录,那就应该在选择安装目录的预加载选项卡里面的输入呗,
其实不然,因为Setup Factory奇怪的机制,如果你选择在预加载选项卡输入代码的话,你会发现,自动读取路径的功能就无法实现了,地址了空白一片,当你点了返回到许可协议页面再点下一步的时候,地址栏上面才会出现读取注册表取得地址,这个问题,我估计是因为Setup Factory优先执行页面生成函数,后执行你写的Lua脚本导致的,这点请多加注意(为了找到这个Bug,我可是不知道测试了多少遍,改了多少遍代码,当一次无意中发现返回再下一步才能实现的时候,那种欲哭无泪的感觉啊,哎)
那么怎么解决问题呢,也很简单,既然不能在这个页面的预加载里面执行,那么就到上个页面的下一步页面执行呗,


这里也就是在许可协议的下一步选项卡里面,把这段代码打进去,让代码在选择安装页面之前就执行,这点请多加注意


然后我在后面多写了一条

if (SessionVar.Expand("%AppFolder%") == "") then
result = Dialog.Message("路径读取失败", "无法找到游戏的安装目录,请手动设置安装路径.", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
end
其实没啥好讲的,就是判断%AppFolder%参数里面是不是空的(用SessionVar.Expand展开%AppFolder%参数,如果是空的话,就调用Dialog.Message显示一个没有自动读取到路径的窗口。




然后我闲着无聊,在下一步选项卡里多做了一个判断,


就是判断游戏目录下面,有木有源程序在,使用的代码如下

if(SessionVar.Expand("%AppFolder%") ~= result4)then
adress = File.DoesExist(SessionVar.Expand("%AppFolder%\\暁の護衛~罪深き終末論~.exe"));
result2 = 6;
if(adress~=true)then
result2 = Dialog.Message("未找到游戏主程序", "未检测到游戏主程序,确定这里是游戏安装路径吗?", MB_YESNO, MB_ICONINFORMATION, MB_DEFBUTTON1);
end
end
  
if(result2~=7)then
Screen.Next();
end
我们先不看第一句话,从第二句开始,使用了一个函数File.DoesExist(),这个函数的作用是,查看指定位置是否存在指定的文件,如果存在返回true,不存在返回false。
我利用了这条函数,根据这条函数的返回值,选择是否使用Dialog.Message,注意,这里我调用的Dialog.Message,使用了倒数第二条类型


也就是,这个信息窗口,会显示是与否的按钮,经过测试,我发现选择是的话,返回的值是6,如果选择的是否的话,返回的值是7
因此根据返回值,设置是否进入下一个页面,亦或者停留在当前页面。


你以为到此,功能就算完善了么?其实不然,我闲着蛋疼,多做了些判断
首先,许可证和选择安装目录之间,如果用户没事找事喜欢按返回,然后按下一步,然后返回,下一步,这样循环怎么办?
总不能返回,然后下一步都要选择一次目录吧
于是,我在许可证页面的下一步选项卡里面,在第一行添加了一句

if(SessionVar.Expand("%AppFolder%") == "")then
...
end

也就是说
一开始就判断默认目录是否是空的,是空的就执行自动读取注册表,不是空的就跳过这些步骤


然后在选择安装目录和准备安装之间,如果用户没事找事喜欢按返回,然后按下一步,然后返回,下一步,这样循环怎么办?
于是,我在准备安装页面的返回选项卡


打了这句话

result4 = SessionVar.Get("%AppFolder%");

把默认安装地址给了变量result4
然后在选择安装目录的下一步选项卡里面,在第一行添加了一句

if(SessionVar.Expand("%AppFolder%") ~= result4)then
....
end

这样就能能判断地址是否有了变更,变更以后就执行接下来的判断,如果没有变更就直接跳到下一页,而不会继续跳出确认按钮。


至此关于自动读取注册表路径到默认安装路径的功能就全部讲解完毕了。

离线cdj68765

发帖
5
金钱
50
威望
5
只看该作者 2 发表于: 2015-03-26
安装完成后,执行某某某

这一步相对简单,我就废话少说了

首先我们在After Installing选项卡里面,先删除掉原先那个结束安装页面,然后点添加,选择Check Boxes

然后在这个页面,我们只需要记得这个变量的名字就行了,然后点操作
在操作里面的下一步选项卡里面,我使用如下代码

if ( check01 ) then
Shell.Execute(SessionVar.Expand("%AppFolder%\\XX.exe"), "open", "", "", SW_SHOWNORMAL);
Screen.Next();
end

代码的意思是,如果check01这个变量有数值了(也就是打钩了)那么执行下面的步奏

Shell.Execute就是用来执行外部程序的,然后后面还是一样,我们需要调用SessionVar.Expand()来返回指定参数的字符串,而不能直接把地址打进去,使用SessionVar.系列函数对参数进行操作是贯穿整个脚本编辑过程的,请牢记

这样一来,整个安装包所有的功能都已经实现了,我将工程文件打包上传给你们,这样你们可以根据教程看的更清楚吧,有问题请PS
Setup Factory 9 工程文件:http://pan.baidu.com/s/1dDtSvlv
稍微做了些修改,看不懂的请联系我
离线axlswd

发帖
95
金钱
910
威望
91
只看该作者 3 发表于: 2015-04-02
感谢楼主的教程
离线圣战

发帖
24
金钱
60
威望
6
只看该作者 4 发表于: 2015-04-03
注册表那个写法是经典,借鉴了几次了,收藏
离线圣战

发帖
24
金钱
60
威望
6
只看该作者 5 发表于: 2015-04-03
今天实现wav格式音乐出了问题了,难道是音乐文件太大了?
离线圣战

发帖
24
金钱
60
威望
6
只看该作者 6 发表于: 2015-04-03
看了下。。。MP3转换成Wav的居然变成50多M了。。。
离线圣战

发帖
24
金钱
60
威望
6
只看该作者 7 发表于: 2015-04-03
上图已经换了个小的music.wav文件,一般播放器放得出来没问题,安装时就是没声音
~~~~(>_<)~~~~  不知道哪儿错了
离线mofei8383

发帖
35
金钱
350
威望
35
只看该作者 8 发表于: 2015-04-16
受教了,图文并茂,形象生动地为我们演示了最基本也最实用的代码。感激
离线cdj68765

发帖
5
金钱
50
威望
5
只看该作者 9 发表于: 2015-05-19
回 9楼(shenyongran) 的帖子
很抱歉,这么晚才看到你的回复以及问题,然后我想了下,用了比较迂回的方式解决了这个问题
path=SessionVar.Get("%LaunchUserApplicationDataFolder%");
path2 = String.TrimRight(path, "Roaming");
path3 = String.Concat(path2, "Local");
首先我查了几个可以调用的变量,发现%LaunchUserApplicationDataFolder%可以返回地址C:\Users\Administrator\AppData\Roaming
于是我用path=SessionVar.Get("%LaunchUserApplicationDataFolder%");这个指令返回了这个地址
但是我们不需要Roaming,于是我删除了Roaming这几个字符串path2 = String.TrimRight(path, "Roaming");
然后添加了Local字符串path3 = String.Concat(path2, "Local");
最后就得到了你想要的C:\Users\Administrator\AppData\Local地址,
可能有更好的办法来获得,我去想想(比如我最开始想到了查找注册表里面,有关此文件夹的值)