翻譯|使用教程|編輯:況魚杰|2020-01-20 14:43:37.863|閱讀 528 次
概述:在某些情況下,對于正在運行的安裝來說,訪問正在運行的MSI數據庫的表可能很有用。本文提供了使用自定義操作在運行時訪問和臨時修改MSI數據庫表的概述。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
InstallShield是構建Windows安裝程序和MSIX包并直接在Microsoft Visual Studio中創建安裝的最快速最簡單的方法。借助InstallShield,您可以快速適應行業的變化,更快地進入市場并提供引人入勝的客戶體驗。
在某些情況下,對于正在運行的安裝來說,訪問正在運行的MSI數據庫的表可能很有用。本文提供了使用自定義操作在運行時訪問和臨時修改MSI數據庫表的概述。
訪問數據庫表
在VBScript中,Session對象提供了Database屬性,該屬性表示正在運行的MSI數據庫。 (在InstallScript和C中,API函數MsiGetActiveDatabase返回相同的信息。)在自定義操作中,您可以對正在運行的數據庫執行SQL查詢。
執行SQL查詢
下面是在運行時訪問MSI數據庫的步驟。
步驟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操作的屬性列表中,指定以下設置:
與訪問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數據庫訪問時,應牢記以下幾點:
推薦文章:
=================================================
如果您想要購買正版授權InstallShield,可以聯系咨詢相關問題。
關注慧聚IT微信公眾號???,了解產品的最新動態及最新資訊。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自: