Installshield 12 中文系列教程之自定义安装行
Installshield 12 中文系列教程 之 自定义安装行为(二)使用自定义操作
使用自定义操作
InstallShield支持使用自定义操作来调用一个 .DLL 函数;执行一个 .EXE 文件;运行VBScript,Jscript或者InstallScript代码;运行另外的安装包。
InstallShield把创建和执行这些任务分为下面几个步骤:
1、在Custom Acitons 视图下使用Custom Acitons Wizard创建一个自定义操作。
2、决定你的自定义操作何时运行
3、通过把它插入到(sequence)执行顺序中,或者放置到对话框控制事件的结果中(只限于BASIC MSI项目)来执行这个自定义操作。
注意:只在 Merge module项目中,你可以通过在DirectEditor中修改ModuleInstallExecuteSequence表来控制在Mergemodule执行自定义操作。当你在安装项目中添加了一个Merge module,包含在Mergemodule中的所有自定义操作和对话框都插入到了安装顺序中,并且可以由Sequences视图中可以处理。
使用自定义操作向导
你可以使用自定义操作向导了创建一个或修改一个现有的自定义操作。
要执行自定义操作向导:
1、打开Custom Actions 视图
2、右键单击Custom Actions并选择Custom Action Wizard 。执行Custom Action Wizard。
3、按照向导面板的提示创建自定义操作。
在Custom Actions 视图中,你也可以不使用向导来创建一个自定义操作。
在CustomActions 视图中创建一个自定义操作
推荐使用Custom ActionWizard来创建一个自定义操作。向导带你通过所有需要的步骤来创建一个自定义操作并提示相关信息。你也可以不使用向导来创建一个自定义操作。
要创建一个自定义操作:
1、打开Custom Actions 视图
2、右键单击Custom Actions并选择你想创建的自定义操作的类型。
3、通过选择自定义操作并按F2键,重新命名自定操作。
4、设置自定义操作的相关属性。
设置自定义操作的属性
根据你想创建的不同类型的自定义操作,它的属性也许会有不同的含义。例如,如果你的操作调用了一个存储在 .MSI 包中的可执行文件,Source属性表项中需要有指向这个你想要调用的可执行文件的名称。目标属性是这个文件的命令行参数。
要获得更多的属性信息,参考Windows Installer Help 库中的CustomAction Table
自定义操作属性表:
属性
描述
DLL Filename
输入你想在自定义操作中使用的 .DLL文件的路径。你也可以通过从你的Binary 表中选择,或者单击 Browse for file 找到它。
这个.dll 文件必须符合Windows Installer 函数所需的标记。
注意,这个设置用于 DLL 自定义操作。
Function Name
输入你想调用的函数名称。这个设置用于 DLL 自定义操作。
Return
Processing
指定这个自定义操作将如何处理。下面是有效的选项:
•
异步进行(不等待完成)
•
异步进行(等待exit代码)
•
同步进行(检查exit代码)
•
同步进行(忽略exit代码)
这个标志用来指定主程序和自定义操作线程之间是同步(安装器等待自定义操作线程完成再继续主安装进程)的还是异步(安装器运行自定义操作与主安装程序同时进行)的。
注意有一些选项不适用于部分类型的自定义操作。只有选项适用于已选择自定义操作类型的才在列表中可用。
In-Script Execution
选择哪种交互的序列将触发你的操作。
这些选项复制操作代码到执行、回滚或者确认脚本。如果你选择了一个Terminal Server Aware 选项,自定义操作在终端服务器每个机器安装时扮演用户角色。
Source
如果你选择执行一个可执行文件(.exe 文件),在Windows Installer中调用一个 .dll文件,或执行一个 VBScript或者Jscript,这个属性包含从表中来的表项名称,象 Binary 表或者 Property 表。如果你选择设置一个属性或目录,从关联的表项中输入属性或目录名称。如果想获得这个属性的更多信息,可以查看Windows Installer 编程参考中有关你调用的自定义操作类型的部分。
Target
根据你创建的自定义操作的不同类型,目标属性可以是一个命令行参数,一个函数名,或者一个格式化字符串。对于可执行文件,这些属性是一个命令行参数 –s 来让可执行文件在寂静模式下运行。如果你从Windows Installer的 .dll 文件中调用一个函数,或者运行一个Jscript 或VBScript代码,这些属性应该包含一个
函数名。输入一个格式化文本字符串,如果你设置的是一个属性或者目录,它将作为你的属性表中的一个新值。标准的 .DLL 文件在指定的格式字符串中必须有函数名,参数和返回类型。
Type
输入你想创建的操作的数字类型值。
在本地增加的Windows Installer 自定义操作类型中,InstallShield支持针对于InstallScript自定义操作和针对于从一个标准 .DLL 文件中调用函数。
Comments
在这个操作的 Comments 区域输入关于这个操作的注释。这些注释是用于内部使用从不会显示给最终用户。
Help File Path
单击省略号按钮(…)来找到描述这个自定义操作行为的文件。这个文件应该是一个基于文本的文件,比如象一个 .txt , .htm ,或 .rtf 文件。
在Basic MSI, InstallScript MSI, 和merge module 项目编译时,InstallShield 把这个文件的内容写进ISCustomActionReference 表中的Description列中。
如果你在使用一个项目的 Direct Edit 模式,当你选择这个帮助文件就是你在ISCustomActionReference 表中的Description列,其中是InstallShield 写进的文件的内容。另外,InstallShield 会把这个设置修改成只读,并且这个值作为 [ Text Data] 显示。
对于InstallShield 内置的自定义操作,InstallShield 会把这个设置修改为 只读,并把InstallShield 自定义操作作为显示值。
自定义操作类型
Type值是一个显示在自定义操作的属性表中,表现为几个对于自定义操作的可用选项。在后台,是通过使用 OR 操作符来把几个在WindowsInstaller CustomAciton表中可用的Type 列联合计算的十进制值。InstallShield 也对扩展的自定义操作类型提供支持,象InstallScript 自定义操作和 标准 .dll文件函数。
WindowsInstaller 支持库通过数字类型来引用自定义操作。当你在项目的Custom Actions视图中添加了一个自定义操作,自定义操作类型号自动计算,并且MSI 类型号属性被设置为这个数。例如,执行一个在Property 表中存储完全路径的可执行文件作为自定义操作类型 50 。要学习其他自定义操作的基本类型使用的值,查看Windows Installer 帮助库中的Summary List of All Custom Action Types部分。
InstallScript 自定义操作
为了在Windows Installer 安装程序中使用InstallScript 函数,你首先需要创建一个自定义操作来调用你的脚本。最简单的方法是使用 Custom Action Wizard 。
在这个向导中主要的面板是:
•
操作类型面板(Action Type Panel)
•
操作参数面板(Action Parameters Panel)
•
响应选项面板(Respond Options Panel)
•
插入顺序面板(Insert into Sequence Panel)
当你完成了向导,就创建了一个类型为65536的自定义操作。这个自定义操作的类型没有定义在Windows Installer帮助库中。因为WindowsInstaller不支持InstallScript,InstallShield创建操作类型65536.
注意:你在InstallScript MSI项目中不应该在UserInterface 顺序中插入使用一个InstallScript 自定义操作。你可以在InstallScriptMSI项目中使用脚本所提供的用户界面。
自定义操作返回值
根据你在自定义操作向导中附加选项中选择的内容,Windows Installer 在继续进行安装程序之前将会等待一个成功的返回代码。你的自定义操作必须依照它的情况返回下列值中的一个。
返回值
描述
ERROR_FUNCTION_NOT_CALLED
这个自定义操作没有执行。
ERROR_INSTALL_FAILURE
这个自定义操作失败。
ERROR_INSTALL_SUSPEND
这个自定义操作暂停,但是它将会在以后恢复运行。
ERROR_INSTALL_USEREXIT
这个自定义操作不能成功完成因为用于终止了它。
ERROR_NO_MORE_ITEMS
这个自定义操作成功,但是剩余的操作将被跳过。
ERROR_SUCCESS
这个自定义操作执行成功。
如果你是一个InstallScript 自定义操作的作者,你的入口点函数能返回ERROR_SUCCESS 或 ERROR_INSTALL_FAILURE 。这些常量当你在脚本中包含了 Iswi.h 文件时就被定义了。InstallShield脚本引擎会向WindowsInstaller 报告任意其他例外情况。
In-Script 执行
当你创建了一个自定义操作,在自定义操作向导中的 Respond Options 面板中的In-ScriptExecution 属性必须设置。操作按照它出现的次序执行。然而,在典型安装期间次序会运行许多次。In-Script Exection属性可以让你选择哪个次序将触发你的操作。
(Terminal Server Aware)
如果你选择了Terminal Server Aware选项-例如,Immediate Execution(Terminal ServerAware)这个自定义操作在终端服务器上的每机器安装时会模拟最终用户。
Immediate Execution
象它的名字一样,当内部的Windows Installer安装脚本开始编译时Immediate Execution运行。当执行一个 .msi 文件是,Windows Installer 服务把安装数据库中的所有表转换成内部脚本。(这个内部脚本不同于InstallScript代码)这个脚本的建立是通过循环它们按照在安装中出现的次序的所有操作而产生的。当一个操作的In-Script Execution属性设置为Immediate Execution,这个操作被执行。因此,这个操作将在其他文件传输之前执行,可能甚至是在安装程序的用户界面完全加载之前。
作为规则,自定义操作预订的立即执行(immediate execution)不会修改目标系统,只是设置属性或查询目标系统(例如,看看目标系统是否符合你的项目系统需求)。自定义操作设置Windows Installer 属性时必须设置为立即执行(immediateexecution),并且自定义操作出现在用户界面次序中(User Interface)也必须设置为立即执行(immediateexecution)。
因为这些类型的操作在系统的任何修改之前运行。它们不能依赖通过安装程序安装的文件。
延缓执行(Deferred Execution)
在通过Windows 安装服务运行Immediatie Execution 期间产生内部脚本时,会出现Deferred Execution(延迟执行)。在脚本完全的生成后,Windows安装服务会运行最近的编译脚本。这个脚本会遍历次序中的所有操作并按照次序执行它们。然而,如果一个操作设计为立即执行(Immediatie Execution),这个操作将在延缓执行期间不会再次运行。
在延缓执行(Deferred Execution)期间操作的执行可以象访问系统文件一样访问已经安装的部分文件。这样,你可以在安装程序运行期间调用一个自定义操作,它可以从你的项目中已经安装的 .DLL 文件中调用一个函数。然而,延缓执行(Deferred Execution)自定义操作要正常运行它必须放置在InstallInitialize 和InstallFinalize 之间。
对于依赖于已经安装到系统上的文件或者依赖于已经完成的某些系统的变化的自定义操作,必须设计为延缓执行(Deferred Execution)。
回滚执行(Rollback Execution)
回滚的产生是在安装程序遇到一个错误或者最终用户在安装完成之前取消了安装的时候。回滚执行(Rollback Execution)选项允许你设置只有在回滚期间执行的操作。因此,任何回滚执行(Rollback Execution)的操作都被作为延缓执行操作写到了安装脚本中。与延缓自行不同,回滚执行操作只有在回滚期间才会执行。(回滚自定义操作只有在延迟执行安装失败期间才会执行。)
任意自定操作在安装期间对目标系统进行的修改都应该在回滚期间使用回滚执行自定义操作来还原。例如,如果你有一个自定义操作创建了一个文件,你应该创建第二个自定义操作来删除它,并且第二个操作应该设置为回滚执行。(一个回滚的自定义操作应该安排在自定义操作之前。)
Commit Execution
CommitExecution操作直到InstallFinalize 操作完成之前都不会执行。这意味着它一直等待,直到安装程序完成文件传输,注册COM服务,创建快捷方式和注册表项。然后,其他的设置为Commit Execution的操作按照它们出现次序依次执行。
例如,如果你有一个自定义操作创建了一些临时文件,你应该建立第二自定义操作来删除这些文件,它应该设置为Commit Execution 。
在系统上下文中延缓执行
象延缓执行操作,这些操作直到通过Windows安装服务生成的脚本运行之前,都不会执行。然而,这些类型操作的执行没有模拟用户。
记录自定义操作的行为
要在项目中记录自定义动作的行为:
1、创建描述自定义操作的预期的行为的一个文件。 该文件应是基于文本的文件如.txt、.htm 或.rtf文件。 请注意每个自定义操作应该具有它自己的文档。
2、在视图列表中,Behavior and Logic下面,单击Custom Actions
3、在Custom Actions窗口中,单击你想记录的自定义操作
4、在Help File Path的设置中,单击省略号按钮(…)查找用于描述自定义操作行为的文件。
技巧:你可以指定InstallShield在编译时,是否把每一个自定义操作的帮助文件加入到.MSI文件中。要查看更多信息,查看在Releases视图中项目配置中关
于 包含自定义操作帮助设置(Include Custom Action Help Setting)的描述
创建符合 Windows Vista 徽标要求准则的自定义操作
如果你正在应用Windows Vista ,你的应用程序必须符合Microsoft’s Windows Vista Quality Programe 需求。你可以使用Windows Vista QualityValidation Suite,它包含InstallShield ICEs ,来检验你的安装包是否符合多数自定义操作相关联的徽标需求。但是,一些需求是不能通过验证组合套装来进行验证的。
下面的需求列表是不能通过Windows Vista QualityValidation Suite或者关联的ISICEs来进行验证的,但是仍然必须符合,达到Microsoft’s Windows VistaQuality Programe 的需求:
•
不要从自定义操作中调用 Global Assembly Cache 工具(Gacutil.exe)。这个工具被设计为不能在安装期间使用。
•
所有的自定义操作必须通过调用MsiProcessMessage函数在WindowsInstaller日志中记录成功或失败信息。
•
自定义操作在安装期间改变的系统状态在卸载期间必须删除或还原。另外,改变系统状态的自定义操作必须与一个延缓和回滚自定义操作成对。
•
这个不能用于自定义操作类型为19(显示一个错误,返回一个失败和结束安装),35(设置安装程序目录),或51(设置一个属性)的操作。
嵌套安装
重要提示:嵌套安装是Windows Installer不推荐的一种功能。有时,安装和嵌套安装失败因为它们很难为最终用户恰当的服务。微软公司推荐,避免使用嵌套安装和嵌套自定义操作来安装确定向公众发布的产品版本。要获得更多信息,查看MSDN网站的Concurrent Installations。
一个嵌套安装是一种自定义操作,即在一个运行的安装程序(称为父产品)中安装或删除另外的 .MSI 包(有时称为子产品)。
提示:在使用嵌套安装自定义操作之前,你应该知道下列限制:
•
嵌套安装不会显示用户界面
•
子产品一般不会出现在最终用户“控制面板”的“添加或删除程序”中,当父产品卸载时,它不会自动的卸载。
创建嵌套安装自定义操作
重要提示:嵌套安装是Windows Installer反对的功能。有时通过嵌套安装的应用程序会失败,应为他们对于终端用户难于恰当的提供服务。微软公司建议避免使用嵌套安装或在安装中嵌套自定义操作来安装产品,最好用户发布成公用版来
替代嵌套。要了解更多查看MSDN网站的Concurrent Installations 部分。
要使用向导创建一个嵌套安装自定义操作:
1、打开自定义操作(Custom Actions)视图
2、右键单击“Custom Actions”并选择“CustomActions Wizard”,打开自定义操作向导。
3、在“Basic Information”基本信息面板,指定名称和注释并单击 NEXT 。
4、在“Action Type”面板中的“Type”列表中,选择,“Launch another .msi Package”。在“Location”列表中,选择“Includedwithin your main setup”(包含在主安装中)。
5、在“Action Parameters”面板,浏览找到你想执行的 .msi 文件的位置。(为了便于说明,假设子产品是一个所有文件压缩在 .msi 文件的包)“Target”框可以让你指定切换到子安装时传递的命令行参数。例如,要使用默认的设置来安装子安装所有的功能部件,并且对于“ALLUSERS”属性使用与父安装程序相同的值,在“Target”中输入下列内容:
ARPSYSTEMCOMPONENT=1 ADDDEFAULT=ALLALLUSERS=[ALLUSERS]
你可以象在父安装程序中一样通过简单的表达式来使用与INSTALLDIR相同的值。
6、接受“Additional Options”面板中默认的选项并单击“NEXT”完成向导。
在(Sequences)次序中插入嵌套安装的自定义操作
当你创建一个自定义操作后,你需要把它插入到一个次序中。
要在次序中插入一个嵌套安装的自定义操作:
1、打开Sequences视图
2、在Installation次序之下,双击“UserInterface”。显示标准和自定义操作的列表。
3、选择这个新建的自定义操作。
4、在“Condition”框中,选择“Not Installed”确保这个嵌套的安装只有在父程序第一安装时才被安装。
5、单击“OK”
删除子项目
当父程序被卸载时,子项目不会自动卸载。然而,你可以创建第二个嵌套安装的自定义操作来完成这个工作
要创建自定义操作:
1、打开自定义操作(Custom Actions)视图
2、右键单击“Custom Actions”并选择“CustomActions Wizard”,打开自定义操作向导。
3、在“Basic Information”基本信息面板,指定名称和注释并单击 NEXT 。
4、在“Action Type”面板中的“Type”列表中,选择,“Launch another .msi Package”。在“Location”列表中,选择“Anapplication that is advertised or already installed”。
5、在“Action Parameters”面板,浏览找到你想卸载的 .msi 文件的位置。在“Target”中保留默认的属性:
ALLUSERS=[ALLUSERS] REMOVE=ALL
6、接受“Additional Options”面板中默认的选项并单击“NEXT”完成向导。
指定自定义操作的次序
1、打开Sequences视图
2、在Installation次序之下,双击“Execute”。显示标准和自定义操作的列表。
3、右键单击“InstallValidate”并单击“Insert”。打开“插入操作对话框”
4、选择这个新建的自定义操作。
5、在“Condition”框中,输入下列内容:
REMOVE="ALL"
6、单击“OK”
这个自定义操作将在父程序卸载时卸载子安装程序安装的部分。
注意:当你建立一个嵌套安装的自定义操作来执行另一个 .msi 包的时候,在“Location”中如果设置为“Stored on thesource media”,你需要明白下列内容:
1、子安装不能压缩进一个 Setup.exe 安装执行文件中。
2、如果子安装的文件没有压缩进一个 .MSI 库中,你必须手动复制子安装文件到父安装程序发布目录的“Disk1”目录中。
基于版本标记有条件的执行自定义操作
当你的安装程序编译时,InstallShield 自动的在Property表中添加了一个叫做ISReleaseFlags。这个属性包括所有的在编译时包含进的版本标志。这些标志出现的形式与在 “Releases”视图中的Release Flags 属性中相同。多个标记使用逗号分隔。
通过下面的方法,一个自定义操作可以根据版本标志来有条件的执行。
设置条件属性
有条件的执行一个自定义操作的最简单方法是,当你在次序中插入自定义操作时设置条件属性(Condition property)。按照这样,你可以在条件属性中输入一个条件,象ISReleaseFlags><"MyReleaseFlag"。如果在子字符串“MyReleaseFlag”包含在ISReleaseFlags 属性的值中,条件成立。
调用MsiGetProperty
在你的自定义操作中基于版本标记设置一个条件的另一个比较费事的方法是通过自定义操作调用MsiGetProperty
。除了确定这个操作是否执行,你还可以指定操作将要执行那些代码。例如,你可以为所有情况都使用一个从 .DLL 文件中调用的函数,但是通过在函数内部的逻辑条件针对每种不同的情况提供不同的功能。
按照这种方法有条件的执行你的自定义操作的缺点是你只能使用脚本或 .dll 自定义操作。并且你的自定义操作只能在后台执行。当自定义操作执行是,它可以检查在编译的版本中是否包含指定的版本标记。如果标记存在,自定义操作继续执行,如果标记不存在,操作退出。
克隆自定义操作
InstallShield提供了选项来复制或者克隆你的自定义操作。克隆会创建一个新的自定义操作,它与原始的自定义操作具有相同的类型,所有相同的属性和值。你额可以使用克隆来创建多个具有相似属性的自定义操作,而不必手动设置每一个自定义操作的属性。
注意,克隆选项只是克隆自定义操作。它不会插入自定义操作到任意的安装次序中。
要克隆一个自定义操作:
1、打开Custom Actions 视图
2、右键单击你想克隆的自定义操作,并选择“Clone”
例:在安装中调用 MessageBoxA
要在自定义操作中调用Windows API函数 MessageBoxA()来显示一个信息框:
PartA :执行自定义操作向导(Launch theCustom Action Wizard)
1、打开Custom Actions 视图
2、右键单击Custom Actions 并单击Custom Action Wizard
PartB:开始定义操作(Start a Custom Action)
1、在Basic Information面板中,输入自定义操作的名称,CA_Example ,单击Next。
2、在Action Type 面板中,自定义操作的类型(Type),选择从动态链接库中调用一个函数(Call afunction in a standard dynamic-link library)
3、MessageBoxA 函数是位于User32.dll 中的,这个文件可以在每一个支持的Windows平台上找到。在Location列表中选择Destinationmachine search path并单击Next。
PartC:提供函数定义(Provide the Function Definition)
MessageBoxA()有下列语法:
int MessageBoxA (hWnd, lpText, lpCaption,uType);
在函数定义面板中指定这些信息:
1、在Name框中,输入MessageBoxA
2、在最后的Arguments框单击指定第一参数。编辑区域的每一参数知道它们符合下面的列表
Type
Source
Value
HWND
Constant
MsiWindowHandle
STRING
in Property
MESSAGEPROP
STRING
in Property
CAPTIONPROP
NUMBER
Constant
1
在HWND类型的Value 列表中,选择MsiWindowHandle。把HWND设置为这个值可以确保你的消息框将不会隐藏在安装窗口之后。MESSAGEPROP 和 CAPTIONPROP属性在列表中不可用。当你在这些Value列表中输入这些名称后,他们会添加到属性管理器中(Property Manager)
3、在Return Type列表中,选择void。(尽管MessageBoxA()不会返回一个数,检查属性中的这个值超出了本例的范围。)
4、单击“Next”来前进到Action Parameters面板
PartD:为MessageBoxA指定源(Specify the Source for MessageBoxA)
在自定义向导中下一个重要的设置是在自定义参数面板中(ActionParameters panel)的 Source 区域。MessageBoxA是位于User32.dll中。单击浏览按钮来在你的Windows系统文件夹中定位User32.dll 。(System32文件夹)
在向导的下个面板中,单击下一步接受默认设置,并在总结(Summary)面板中单击完成向导并添加CA_Example到项目
PartE:初始化属性值(Initializethe Properties’ Values)
对于MessageBoxA()中的字符串参数,象上面过程中描述的,在属性中已经提供了。下个步骤就是给这些属性一个值:
1、打开Property Manager查看项目的安装属性。MESSAGEPROP 和CAPTIONPROP是通过自定义操作向导创建的。
2、找到MESSAGEPROP并单击Value列,输入一个值。这里我们输入“Can you see this text?”
3、把CAPTIONPROP设置为“Custom Action Example”
PartF:插入自定义操作到一个次序中(Insert the Custom Action into a Sequence)
为了执行这个自定义操作,你必须把它放置到一个次序中(place it intoa sequence)或者把它作为一个对话框事件的执行结果(make it theresult of a dialog’s control event)。
注意:因为 merge module 它自己没有任何次序,你在这个例子继续进行之前必须首先编译这个模块并把它包含进一个安装项目中。
按照下面的步骤把CA_Example 插入到安装项目的安装次序下面:
1、打开Sequences 视图。
2、在 Installation 次序中,双击User Interface来显示UserInterface次序中所有的操作和对话框。
3、右键单击MigrateFeatureStates操作并单击Instert。打开Insert Action 对话框。
4、在对话框顶部的列表中,选择Merge ModuleCustom Actions (对于Merge Module项目)或者CustomActions(对于安装项目)
5、在自定义操作的列表中,选择CA_Example。
6、单击OK。
CA_Example就直接的添加到安装次序中MigrateFeatureStates的后面。
PartG:测试调用MessageBoxA()(Testthe Call to MessageBoxA)
1、编译发布。(如果你没有在项目中添加任何构件或者文件将收到一个编译和运行时错误)
2、在Build 单击Run
InstallShield 运行安装程序。然后 Welcome对话框出现,一个Custom Action Example 的消息框打开。
在标准 .dll 文件中调用函数
尽管在写一个自定义操作时Windows Installer限制你能传递到一个.dll文件中的函数的参数,InstallShield提供了一种解决方式,让你能够传递任意参数到一个函数并存储返回值。注意这函数必须使用 __stdcall 调用惯例。如果没有按照惯例使用函数所带的多余一个的参数将不能正常工作。
你可以在自定义操作向导的操作类型面板中通过选择“Call a function in a standard
dynamic-linklibrary”选项来指定从一个标准 .dll 文件中调用函数。在下一个函数定义面板中,允许你指定函数的参数和返回值。
注意:如果你调用的函数的.dll文件是这个安装项目安装到系统中的,那么这个操作应该设计为延缓的(针对于In-Script Execution的属性),你调用的这个.dll文件必须是构件的关键文件。
对于自定义操作调用函数的标准 .dll 文件存储于Binary 表中的,不能计划为延缓执。
指定参数和返回值作为格式化的字符串
尽管这种方式是不推荐的,你仍然可以在自定义操作的属性表中直接编辑函数的参数。函数目标属性的格式是按照下面的:
DataType1=[PropertyName1]DllName::FuncName(in DataType2="Value",DirectionDataType3=[PropertyName2])
DataType1=[PropertyName1]
DataType1的类型可以是void, STRING, BOOL, NUMBER, HWND, HANDLE, 或者POINTER。PropertyName1是属性管理器中的一个属性名称。
如果返回值是void ,那么=[PropertyName1]是被忽略的。
DLLName
指定 .dll文件的名称,没有点或者文件扩展名。
FuncName
你想调用的函数名称
in DataType2="Value"
这个是参数是一个常量的格式。DataType2的类型可以是void, STRING, BOOL, NUMBER, HWND, HANDLE, 或者POINTER。Value 是你想传递的这个参数的数据。常量数据类型总是加上 in 前缀。
DirectionDataType3=[PropertyName2]
这个是引用Windows Installer 属性的值得参数的格式。Direction可以是 in ,inout或者out。更多的属性类型查看函数定义面板中的参数源部分。DataType3的类型可以是void, STRING, BOOL, NUMBER, HWND, HANDLE, 或者POINTER。PropertyName2是一个属性名称,它的值将通过函数传递或者设置,依赖于Direction设置的值。
举例:
对于在例子:CallingMessageBoxA in an Installation中创建的自定义操作,目标值读取:
voidUser32::MessageBoxA(in HWND=0, in STRING=[MESSAGEPROP], in
STRING=[CAPTIONPROP],in NUMBER=1)
在这个例子中,数据类型是void ,inHWND=0 表示一个数字值0,MESSAGEPROP 是一个包含字符串的属性,它将要传递给 User32.dll 中的函数MessageBoxA 。
在Windows Installer 中的 .dll 文件中调用函数
专门为 Windows 安装程序自定义操作编写的一个.dll 文件函数可以接受仅将句柄作为一个参数传递到安装程序数据库。下面的步骤解释了你如何在你的自定义操作中从 .MSI数据库中取回信息。
你通过在自定义操作向导的操作类型面板中选择“Call a function in a Windows Installerdynamiclink library”指定你的自定义操作使用Windows Installer的.dll文件(自定义操作类型为1和17)
其中之一是在操作类型面板中选择“Call a function in a standard dynamiclink library”,在这种情形下,InstallShidld允许你指定函数的参数。
有关传递参数到专门为Windows Installer编写的dll中的函数,这里主要有三个步骤:
1、准备好你的.dll 文件。
2、建立一个自定义操作,并把它插入到某个次序中
3、使用“Property Manager”传递参数。下面详细解释这些步骤。
准备 .dll 文件
为了你在自定义操作中传递数据到一个 .dll文件中的函数,这个你要传递数据的函数需要调用MsiGetProperty 函数,它可以取回一个安装器属性值。在下面的例子,它取回了一个公共属性MYPROPERTY的值。
UINT__stdcall MyActionName(MSIHANDLE hInstall)
{
TCHARszValue[51] = {0};
DWORDdwBuffer = 50;
MsiGetProperty(hInstall,TEXT("MYPROPERTY"), szValue,&dwBuffer);
MessageBox(GetForegroundWindow(),
szValue,
TEXT("Valueof MYPROPERTY"), MB_OK | MB_ICONINFORMATION);
returnERROR_SUCCESS;
}
更多的信息,参考Windows Installer帮助支持库中的MsiGetProperty部分。
如果你使用C++编译器,编译你的.dll 文件,确保编译器不会更改从 .dll文件中到处的函数名。对于Microsoft Visual C++,例如你可以创建一个 .def 文件,它指定了从你的 .dll文件中要导出的函数名称。一个典型的 .def文件看起来像下列的:
LIBRARY MyActions
EXPORTS
MyActionName
有关函数名称修饰的更多信息,参考编译器的文档。
创建自定操作并把它插入的次序中
第二步是创建你的自定义操作并把它插入到安装中的某个次序中。使用自定义操作向导来创建自定义操作,使用次序视图来插入。
使用属性管理器(Property Manager)来传递参数
要使用属性管理器来传递新的参数:
1、打开属性管理器
2、滚动到属性表格的最底部并单击最后一行添加一个新的属性
3、在Name 列,输入你想使用MsiGetProperty 来返回的属性名称(在这个例子中为MYPROPERTY)
4、在Value 列,输入你想传递的值。例如,如果你想传递你的网站的URL,输入http://www.mycompany.com
在自定义操作中传参数到一个.dll文件中的函数
这里有许多的原因是为什么你可能需要传递参数到一个自定义操作的函数。例如,你可能想在自定义用户界面中为WEB注册或者用户名属性传递URL。尽管,WindowsInstaller不直接的支持传递参数到一个 .dll 文件中的函数。
对于Windows Installer的.dll文件的入口点函数只能有一个参数,它是到数据库的句柄。要学习更多传递参数的内容,参考在Windows Installer 中的 .dll 文件中调用函数部分。
要在InstallShield中完成这个:
1、在自定义操作向导的操作类型面板,选择Call a function in a standard dynamic-linklibrary
2、在下一个面板中,指定你想InstallShield传递到函数的参数。
在函数调用时指定功能部件和子功能部件
在InstallShield中,功能部件是引用一系列构件和子功能部件的总和。子功能部件是位于其他功能部件之下的,它们之间的关系类似于文件夹和子文件夹。
顶层的功能部件是最高层次的功能部件。顶层功能部件从来不能被引用为子功能部件。
如何引用功能部件和子功能部件
一些功能部件函数和安装类型对话框函数会询问你是引用一个单独的功能部件,另外一些会询问你引用多个功能部件。
引用单个功能部件
要引用单个功能部件,使用功能部件的名称。要引用一个子功能部件,使用一个路径似的表达式,每一个层次的功能部件都使用双反斜杠分隔。例如,要指定顶层功能部件Help Files下面的子功能部件 Tutorials,在安装脚本中使用下列表达式:
szFeature= "Help Files\\Tutorials";
要引用Tutorials下面的CBT子功能部件,使用下列表达式:
szFeature= "Help Files\\Tutorials\\CBT";
引用多个功能部件
一些功能部件和安装类型对话框函数,象SdFeatureMult ,显示多个功能部件和它们的子功能部件。因此,你可以通过指定高于它们层级的功能部件就可以引用多个功能部件。要引用多个顶级的功能部件,使用一个空字符串(“”)。
例如:如果你传递一个空字符串到SdFeatureMult 函数,在相应的对话框左侧,根据 MEDIA 系统变量的值,在窗口中您创建的脚本的组件设置中显示所有顶级功能部件。所有子功能部件显示在右侧窗口中。
执行可执行文件
在安装中执行一个可执行文件常常用于安装第三方工具,显示一个readme文件,或者显示一个WEB页面,这个页面包含安装的产品的最新的信息。要从安装中执行一个可执行文件,你需要在自定义操作视图中添加一个自定义操作;在项目中包含一个自定义操作是执行一个可执行文件的唯一方法。
你可以使用自定义操作向导来创建一个自定义操作,它在安装中执行一个可执行文件。下面列出的每一个面板和表项是你要执行一个可执行文件而需要设置的。
基本信息面板(Basic Information Panel)
面板选项
值
Name
提供一个有意义的自定义操作的名称。这个名称只在产品内部使用并且只是为了便于相互区分
Comment
这个自定义操作的注释
操作类型(Aciton Type)
面板选项
值
Type
选择你想创建的自定义操作的类型。在本例中选择Launch an executable
Location
这个选择项的设置依赖于在安装期间要执行的目标可执行文件的位置。因为Notepad在每台机器上都有,它是这个自定义操作的目标。因为Notepad几乎保证在目标机器的Windows或WINNT目录,你额可以使用 Directory 表来指向它。因此,选择Stored in the Directory table
操作参数(Action Parameters)
面板选项
值
Source
自从你选择了从存储在Directory表中执行一个可执行文件,你就给出了一个选择列表,它显示了Directory中的所有当前表项。这些选项中的一个是WindowsFolder 。选择这个选项指向Notepad,不需要指定硬编码路径。
Target
对于这个选项,你需要输入目标文件相对于Source选项的指定目录。输入Notepad.exe 并单击下一步按钮继续。
附加选项(Additional Options)
面板选项
值
Wait for the ction to finish executing
如果你想安装进程暂停直到自定义操作完成,选择这个选项。在本例的中,安装将保持暂停直到Notepad关闭。
Ignore custom action return code
如果你不想从自定义操作返回一个代码---比如像成功或失败---你可以选择忽略它。
In-Script Execution
选择Immediate execution ,一旦在脚本中遇到它就立即执行这个操作。
Execution Scheduling
选择Always execute ,确保每次遇到自定义操作都执行。
插入自定义操作到次序中
当你创建了一个自定义操作后,你必须在 Sequences 视图中把它插入到某个次序中。
使用 Msiexec.exe 来执行第二个WindowsInstaller 安装
执行第二个 .MSI 安装包的另一个方法是创建一个自定义操作执行 Msiexec.exe 取代使用嵌套安装的自定义操作类型。按照这种方式执行第二个安装,原因是它运行它自己的进程并在目标系统上创建适合的条目。另外的,当你按照这种方法执行第二个安装时,卸载过程更加有效。注册表项被正确清理,并引用计数准确递增和递减。
创建一个自定义操作
第一个步骤是创建一个自定义操作,最简单的方式是使用自定义操作向导。
要使用向导创建一个自定义操作:
1、打开自定义操作(Custom Actions)视图
2、右键单击“Custom Actions”并选择“CustomActions Wizard”,打开自定义操作向导。
3、在“Basic Information”基本信息面板,指定名称和注释并单击 NEXT 。
4、在“Action Type”面板中的“Type”列表中,选择,“Launch an executable”。在“Location”列表中,选择“Stored in the Directory table”。Directory 表允许你选择预定义的目录,象Msiexec.exe所在的SystemFolder 。
5、在“Action Parameters”面板,浏览找到你想执行的可执行文件(Msiexec.exe)的位置。在“Target”框中输入你想执行的文件的名称,并包括你想传递给它的命令行参数。例如:
msiexec.exe /i"[SOURCEDIR]AnotherSetup\SecondSetup.msi" /qb
这个内容的第一部分是msiexec.exe,是你想执行的文件的名称。下一个部分,/i,"[SOURCEDIR]AnotherSetup\SecondSetup.msi" ,告诉Msiexec.exe该运行那个安装包。在这个情况下,它执行初始化安装的源目录中的一个目录或一个文件。最后,/qb告诉Windows Installer 服务使用最小用户界面来运行安装。只显示一个进度条。
6、接受“Additional Options”面板中默认的选项并单击“NEXT”完成向导。
插入一个自定义操作到一个次序中
当你建立了一个自定义操作后,你需要把它插入到一个次序中。
要把这个自定义操作插入到一个次序中:
1、打开Sequences 视图
2、在Installation 次序之下,双击User Interface 。显示标准和自定义操作列表。
3、右键单击CostFinalize 并单击Insert ,打开插入操作对话框
4、选择新的自定义操作
5、单击OK 。
接下来,检查你想执行的安装包位于你在操作参数面板中指定的目录中,编译安装,并运行。
注意:一个执行 Msiexec.exe 的自定义操作必须放置在User Interface 次序中,这意味着,如果最终用户在静默模式下运行安装,自定义操作将不会运行。
为其他项目导出自定义操作
要保存自定义操作用于其他项目:
1、打开自定义操作(Custom Actions)视图
2、右键单击你的自定义操作,并单击Export。打开 Export into对胡框。
3、浏览找到另一已有的InstallShield项目文件(.ism文件)。它可以是一个安装项目或者一个合并模块项目,但是这个文件不能被InstallShield的另一个实例打开。
4、单击Open。
这个自定义操作的副本就添加到指定的 .ism文件中。如果其他的.ism文件已经有一个同名但不同属性的自定义操作,那么会打开“ResolveConflict dialog box”解决冲突对话框,来提示你解决这些冲突的选项。
搜索目标系统上的文件
系统搜索视图(System Search View)
系统搜索视图提供了在目标系统安装应用程序之前查找一个特殊文件,目录,注册表或.ini文件。
直接编辑器(Direct Editor: Basic MSIProjects)
WindowsInstaller 使用Signature ,AppSearch和“locator” 表中的记录来表示在目标系统上搜索的文件。如果找到相应的文件,Signature 表包含关于文件被找到的信息,AppSearch表指定一个属性设置为定位文件的完整路径。
例如,要搜索的文件叫做FindMe.exe,使用直接编辑器添加下列记录到Signature 表。
表列
样例数据
Signature
Findeme_sig
FileName
FindMe.exe
注意Signature表其他的区域可以让你指定可选的版本,大小,日期和语言信息。
添加下列记录到AppSearch表中
表列
样例数据
说明
Property
LOCATION_OF_FINDME
必须是一个公用属性
Signature_
Findeme_sig
与Signature表中相同的名称
这里有四个定位器表,你可以指定Windows Installer应该从哪里开搜索文件:CompLocator,RegLocator,IniLocator,DrLocator 。要在一个指定目录中搜索一个文件,使用DrLocator表,例如,要在用户的Program Files目录中搜索 FindMe.exe ,我们添加下列记录到DrLocator表中。
表列
样例数据
Signature
Findeme_sig
Parent
Path
[ProgramFilesFolder]
Depth
2
当AppSearch操作运行时,如果找到相应的文件,公用的属性LOCATION_OF_FINDME将包含在目标系统上到FindMe.exe 完整的路径;如果文件没有找到,这个属性将是未定义的。
安装脚本(InstallScript:InstallScript MSI Projects)
FindFile和FindAllFiles函数可以让你在目标系统上搜索已有的文件。例如,一个执行OnAppSearch事件处理的函数,它用来在用户的Program Files文件夹中搜索一个名为FindMe.exe的文件,可能表现为下列代码:
functionOnAppSearch( )
STRINGsvFoundFile;
begin
FindAllFiles(PROGRAMFILES,"FindMe.exe", svFoundFile, RESET);
MessageBox("FoundFindMe.exe at: " + svFoundFile, INFORMATION);
end;
安装程序完成后执行应用程序
注意,这部分内容用于InstallScript项目
LaunchApp和launchAppAndWait函数用来执行一个可执行文件。例如,下列代码执行一个复制Program.exe到最终用户的 INSTALLDIR目录中,当用户关闭程序窗口返回执行到脚本。
LaunchAppAndWait(INSTALLDIR^ "Program.exe", "", WAIT);
注意,InstallScript 项目使用TARGETDIR 而不是 INSTALLDIR
把文件放在 .msi 数据库中并在安装期间提取它们
SupportFiles视图(在Basic MSI项目中)和Support Files/Billboards视图(在InstallScriptMSI项目中)可以让你存储在安装程序中使用的临时文件,但是它们不会安装到系统中。例如许可文本文件(作为在SDlicense对话框中显示)或者安装中调用的 .dll 文件。这些支持文件在安装程序运行时提取并存储的位置在Windows Installer的属性SUPPORTDIR中。
在Basic MSI和InstallScriptMSI安装程序中,延迟,提交,回滚自定义操作只访问一些Windows Installer内建的属性:CustomActionData,ProductCode和 UserSID 。如果你想在延缓,提交或回滚执行期间让自定义操作访问其他的属性(象SUPPORTDIR),你需要把它们作为CustomActionData 传递。
注意:这里的Windows Installer属性 SUPPORTDIR 的值与InstallScript 的系统变量 SUPPORTDIR的值是不同的。
自定义操作脚本举例
InstallScript
要安装期间访问一个特别的支持文件,Basic MSI项目和InstallScript MSI项目应该引用Windows Installer属性SUPPORTDIR。你可以使用 MsiGetProperty来查询路径,并追加文件名到SUPPORTDIR 的值来构成完整的文件路径。在一个自定义操作的设置中这个正好是[SUPPORTDIR]。
在一个InstallScript自定义操作中,你应该使用象下列的代码:
exportprototype STRING GetSupportFilePathMSI(HWND);
functionSTRING GetSupportFilePathMSI(hMSI)
STRINGszSupportDir[MAX_PATH + 1];
STRINGszMyFile[MAX_PATH + 1];
NUMBERnLength;
begin
//set initial buffer size
nLength= MAX_PATH + 1;
MsiGetProperty(hMSI,"SUPPORTDIR", szSupportDir, nLength);
//reset buffer-size variable
nLength= MAX_PATH + 1;
MsiGetProperty(hMSI,"MYFILE", szMyFile, nLength);
//return full file path
returnszSupportDir ^ szMyFile;
end;
在这个例子里,支持文件的名字存储在 MYFILE 属性中。
C++
在C++中,你应该使用下列代码:
UINT__stdcall ShowSupportdir(MSIHANDLE hInstall)
{
TCHARszSupportDir[MAX_PATH + 1] = {'\0'};
DWORDdwBuff = sizeof(szSupportDir);
MsiGetProperty(hInstall,"SUPPORTDIR",szSupportDir,&dwBuff);
MessageBox(NULL,szSupportDir,"SUPPORTDIRis ...",MB_OK);
}
VBScript
在VBScript中,你应该使用下列代码:
dim strSupportDir
strSupportDir= Session.Property("SUPPORTDIR")
在延缓,提交和回滚自定义操作时访问或设置WindowsInstaller属性
注意:这部分内容用于Basic MSI项目和InstallScript MSI项目
延迟,提交,回滚自定义操作只访问一些Windows Installer内建的属性:CustomActionData,ProductCode和 UserSID 。如果你想在延缓,提交或回滚执行期间让自定义操作访问其他的属性(象SUPPORTDIR),你需要把它们作为CustomActionData 传递。
你可以按照一个立即执行的设置属性的自定义操作来设置另一个符合其名称的自定操作的属性。在延缓,提交或回滚执行期间的CustomActionData这个属性的值的是可用的。
使用CustomActionData来访问一个属性
下面的例子显示了如果在一个延缓的InstallScirpt自定义操作期间访问WindowsInstaller属性SUPPORTDIR属性。
要在一个延缓的InstallScirpt自定义操作期间访问SUPPORTDIR
1、在Custom Actions and Sequences视图中,建立一个设置属性的自定义操作(类型51)叫做GetSUPPORTDIR,它有下列参数:
PropertyName(属性名称):DisplaySupportDir
PropertyValue(属性值):[SUPPORTDIR]
安装执行次序:After InstallInitialize
保留其他设置为空。
2、在InstallScript视图中,建立一个新函数叫做DisplaySupportDir。
3、添加下列代码来显示一个消息框,包含SUPPORTDIR的值。
function DisplaySupportDir(hMSI)
STRING supportDirPath;
NUMBER supportDirPathBuffer;
begin
supportDirPathBuffer = MAX_PATH;
if(MsiGetProperty(hMSI,"CustomActionData", supportDirPath,
supportDirPathBuffer) == ERROR_SUCCESS)then
SprintfBox(INFORMATION,"DeferredExecution","The value of
SUPPORTDIR is %s",supportDirPath);
SprintfBox(INFORMATION,"DeferredExecution","The value of
InstallScript's SUPPORTDIR is%s",SUPPORTDIR);
endif;
end;
4、建立一个InstallScript自定义操作叫做DisplaySupportDir包含下列参数:
Function Name(函数名称):DisplaySupportDir
In-Script Execution :Deferred Execution in System Context
Install Exec Sequence(安装执行次序):After GetSUPPORTDIR
保留其他设置为空。
使用CustomActionData 来访问多于一个属性
如果你想在延缓,提交或者回滚自定义操作是访问多个是Windows Installer 属性,你可以把这些属性打一个包放在CustomActionData中,并在使用时从CustomActionData的值中把它们提取出来。
例如,如果你想接收[INSTALLDIR],[SUPPORTDIR],和 [SetupType]的值,你将在你的类型为51的自定义操作的属性值中如下设置:
[INSTALLDIR];[SUPPORTDIR];[SetupType]
它们彼此之间使用分号分隔。
你可以象下列代码(VBScript)来从CustomActionData的值中提取相关数据
DimPropArray
PropArray= Split(Session.Property("CustomActionData"),";")
INSTALLDIR= PropArray(0)
SUPPORTDIR= PropArray(1)
SetupType= PropArray(2)
'Nowdo something with these variables...
从一个自定义操作中跳出整个安装程序
注意:这部分内容用于 InstallScript 类型项目。
一个返回这个值ERROR_INSTALL_FAILURE的InstallScript进入点函数将导致安装退出。
通过脚本改变ODBC属性
如果你想通过脚本改变ODBC属性(象DBQ和SystemDB),你必须配置这些选项来使用Installer属性。然后你可以在运行时通过脚本来设置这些Installer的属性。例如,你想在InstallShield界面中设置SystemDB为
[SYSTEM_DB_DIR]\MyDatabase 。然后,你想通过脚本调用MsiSetProperty 来把这个值设置为SYSTEM_DB_DIR 。
技巧:
•
在OnMoving 时间之前设置属性值,更适合于在OnFirstUIBefore。在它之后,已经太迟了,因为Installer已经建立了内部的脚本信息,它不能被修改。
•
属性名所有都使用大写字母。
•
如果在Directory表中已经存在SYSTEM_DB_DIR当你设置你的ODBC属性时,省略掉右中括号“]”后面的反斜杠“\”。如果你在属性管理器中定义了它,则必须包括反斜杠。
在一个VBScript 自定义操作中使用INSTALLDIR 变量
注意,这部分内容不能用于 InstallScript 项目
如果你需要在VBScript自定义操作中使用INSTALLDIR 变量,使用Session对象的Property属性。这个对象是每一个VBScript自定义操作都可访问的。
按照下面的样例代码:
szInstallDir= Session.Property("INSTALLDIR")
更多信息,可以参考Windows Installer 帮助支持库中关于 Session Object的介绍。