彩票走势图

打包软件InstallShield提示和技巧:在运行时访问MSI数据库

翻译|使用教程|编辑:况鱼杰|2020-01-20 14:43:37.863|阅读 439 次

概述:在某些情况下,对于正在运行的安装来说,访问正在运行的MSI数据库的表可能很有用。本文提供了使用自定义操作在运行时访问和临时修改MSI数据库表的概述。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

相关链接:

InstallShield是构建Windows安装程序和MSIX包并直接在Microsoft Visual Studio中创建安装的最快速最简单的方法。借助InstallShield,您可以快速适应行业的变化,更快地进入市场并提供引人入胜的客户体验。

点击下载InstallShield最新试用版


在某些情况下,对于正在运行的安装来说,访问正在运行的MSI数据库的表可能很有用。本文提供了使用自定义操作在运行时访问和临时修改MSI数据库表的概述

访问数据库表

在VBScript中,Session对象提供了Database属性,该属性表示正在运行的MSI数据库。 (在InstallScript和C中,API函数MsiGetActiveDatabase返回相同的信息。)在自定义操作中,您可以对正在运行的数据库执行SQL查询。

执行SQL查询

下面是在运行时访问MSI数据库的步骤。

  • 使用SQL SELECT语句打开正在运行的数据库的视图。
  • 执行视图。
  • 获取视图返回的记录,并从所需字段中提取数据。
  • 关闭视图。

步骤1涉及创建SQL SELECT语句。SELECT语句的一般形式如下。

SELECT Fields FROM Tables

例如,要从FeatureComponents表中选择所有字段,查询将如下显示,并使用星号(*)表示所有字段。

SELECT * FROM `FeatureComponents`

为避免与SQL关键字冲突,建议您将字段名和表名放在反引号(`)中。

执行相同查询的另一种方法是显式标识所需的字段名称:

SELECT `Feature_`,`Component_` FROM `FeatureComponents`

您还可以使用WHERE子句来缩小SELECT语句的范围,然后在字段值和常量字符串之间进行比较,或者在两个字段值之间进行比较。 例如:

SELECT * FROM `Control` WHERE `Dialog_`='SetupCompleteSuccess'

比较中使用的常数应放在单引号(')中。

MSI帮助库页面SQL语法描述了可在MSI数据库查询中使用的更多关键字。

注意:MSI仅支持完整SQL语法的子集:例如,不支持LIKE和LEN运算符。

SQL查询返回的是一组与查询匹配的记录。记录或行是一组索引字段,您的自定义操作代码可以使用Record对象的StringData和IntegerData属性检索所需的数据。

例如,假设自定义操作执行以下查询:

SELECT `Feature`,`Level` FROM `Feature`

返回的每个记录将包含两个字段:Feature字段,其中包含功能的字符串标识符,以及该功能的数字Install Level值。在代码中(假设记录对象存储在名为rec的变量中),您将使用以下内容引用所获取记录的第一个(字符串)字段:

rec.StringData(1) ' indexing starts with 1

然后,您将使用以下内容引用已获取记录的第二个(整数)字段:

rec.IntegerData(2)

要确定字段使用的数据类型,可以查看所需表的MSI帮助库页面。打开特定表帮助页面的一种简便方法是在InstallShield的直接编辑器视图中选择该表,然后按F1键。

示例:查询属性表

例如,以下代码从属性表中获取ProductName记录,然后显示ProductName值。(此示例仅是为了说明;在此特定情况下,表达式Session.Property(ProductName)返回相同的信息。)

Const IDOK = 1
Function ReadProductName( )
' open and execute the view
Set oView = Database.OpenView("SELECT `Value` FROM `Property` WHERE
 ` Property`='ProductName'")
oView.Execute
' fetch the one and only ProductName record
Set oRecord = oView.Fetch 
' display the string data from the fetched record
MsgBox "ProductName = " & oRecord.StringData(1)
' clean up
oView.Close
' return success to MSI
ReadProductName = IDOK
End Function 

要在自定义操作中使用先前的代码,请将代码放在名为(例如)ReadProductName.vbs的VBScript源文件中。

接下来,在IDE的自定义操作视图中,右键单击Custom Actions(自定义操作图标,然后选择New VBScript(新建VBScript>Stored in the Binary table(存储在二进制表中,将操作图标重命名为(例如)callReadProductName。

在callReadProductName操作的属性列表中,指定以下设置:

  • VBScript文件名:\ ReadProductName.vbs(ReadProductName.vbs浏览)
  • 脚本功能:ReadProductName(VBS文件中的功能名称)
  • 安装UI序列:SetupInitialization之后
构建并运行产品后,自定义操作将显示一个消息框,如下所示。


与访问MSI属性一样,访问正在运行的MSI数据库仅对计划立即执行的自定义操作有效。

修改数据库表

Windows Installer还支持将临时记录添加到正在运行的MSI数据库中。将临时记录添加到正在运行的数据库中,最常见的用途可能是使用直到运行时才可用的数据填充用户界面元素。(当然,此技术仅适用于Basic MSI项目;对于InstallScript MSI项目,您可以使用InstallScript函数CtrlSetText,CtrlSetList,CtrlSetCurSel等填充和操作用户界面控件。)

例如,假设您要用属性表中列出的每个属性的当前值填充ListBox控件。首先,您可以将ListBox控件添加到ReadyToInstall对话框中(使用InstallShield的对话框编辑器),然后将该控件与属性LISTBOXPROP关联。(如果需要,可以将ListBox属性的Sorted和Sunken设置为True。)但是,不是在设计时填充ListBox控件的Items属性,而是在运行时通过在ListBox表中插入临时记录来填充其项目。

然后,您可以将以下代码放在名为PropDisplay.vbs的源文件中。

Const msiViewModifyInsertTemporary = 7
Const IDOK = 1
Function PropDisplay( )
' open and execute a view to the ListBox table
Set viewlist = Database.OpenView("SELECT * FROM `ListBox`
 WH ERE `Property`='LISTBOXPROP'")
viewlist.Execute
' open and execute a view to the Property table
Set viewprop = Database.OpenView("SELECT * FROM `Property`")
viewprop.Execute
Set recprop = viewprop.Fetch
r = 0
While Not (recprop Is Nothing)
' ListBox record fields are Property, Order, Value, Text
Set reclist = Installer.CreateRecord(4)
 r = r + 1
 reclist.StringData(1) = "LISTBOXPROP"
reclist.IntegerData(2) = r
 reclist.StringData(3) = recprop.StringData(1)
 reclist.StringData(4) = recprop.StringData(1)
 & "=" & Session.Property(recprop.StringData(1))

' insert the temporary ListBox record
 viewlist.Modify msiViewModifyInsertTemporary, reclist

' fetch the next Property record
Set recprop = viewprop.Fetch
Wend
' clean up
viewprop.Close: viewlist.Close
' return success to MSI
PropDisplay = IDOK
End Function 

注意:使用View对象的Modify方法(具有插入临时常量),该方法会修改或添加数据库记录。

在自定义动作视图中,像以前一样,右键单击Custom Actions(自定义操作图标,然后选择New VBScript(新建VBScript>Stored in the Binary table(存储在二进制表中),将该动作重命名为callPropDisplay,在VBScript文件名字段中浏览PropDisplay.vbs,并在脚本功能字段中指定PropDisplay。

然后,您可以在用户界面序列中提前安排操作,也可以在(例如)SetupType对话框的下一步按钮上使用DoAction控件事件。

生成并运行MSI程序包后,显示临时记录的ReadyToInstall对话框可能如下所示。

通常,您需要确保插入临时记录的代码仅运行一次:如果先前的代码运行两次,则先前的代码将生成运行时错误,因为如果具有给定记录的调用带有insert-temporary标志的Modify方法失败, 则主键已经存在。

一种替代方法是使用类似于PropDisplay函数开头的以下代码删除存在的任何临时记录:

Set viewlist = Database.OpenView("SELECT * FROM `ListBox`
 WH ERE `Property`='LISTBOXPROP'")
viewlist.Execute
Set reclist = viewlist.Fetch
' delete any existing LISTBOXPROP records
While Not (reclist Is Nothing)
viewlist.Modify 6, reclist ' 6 = delete
Set reclist = viewlist.Fetch
Wend
viewlist.Close 

此代码块防止与现有ListBox / LISTBOXPROP记录发生冲突,因此,如果用户单击后退按钮然后重新访问ReadyToInstall对话框,则可以防止错误。

与在设计时填充项目的ListBox控件一样,用户在ListBox中的选择(如果有的话)将存储在LISTBOXPROP(在此示例中)属性中。与往常一样,当执行从用户界面序列切换到执行序列时,将仅保留公共属性的值。您可以使用类似的代码在ListBox控件中填充映射的网络驱动器,用户帐户,目录名称或其他数据的列表,这些列表只有在特定目标系统上运行安装时才能发现。

在运行时使用MSI数据库访问时,应牢记以下几点:

  • Windows Installer不支持永久修改正在运行的MSI数据库:您在运行时所做的更改将不会存储在用户系统上缓存的MSI数据库中。
  • 此外,当执行从用户界面序列切换到执行序列时,Windows Installer会重新加载MSI数据库。因此,当执行切换到Execute序列时,对在User Interface序列中对数据库进行的临时修改将丢失。
  • 如前所述,自定义操作只能在立即执行期间访问正在运行的数据库,而不能延迟执行。


以上内容对您使用InstallShield是否有帮助?如果您有其他的疑惑或者建议都可以在评论区留言。

推荐文章:

MSI功能和组件的使用

InstallShield v2019最新更新说明

=================================================

如果您想要购买正版授权InstallShield,可以联系咨询相关问题。

关注慧聚IT微信公众号☟☟☟,了解产品的最新动态及最新资讯。

1561953111.jpg


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@cahobeh.cn

文章转载自:

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP