是的,沒有安裝msi和使用vbscript的解決方案。 在Windows Installer SDK中有一個很好的例子叫做「WiFilVer.vbs」
使用那個例子我把一個快速的示例腳本放在一起,它完全符合你的需要。
set installer = CreateObject("WindowsInstaller.Installer")
const READONLY = 0
set db = installer.OpenDataBase("<FULL PATH TO YOUR MSI>", READONLY)
set session = installer.OpenPackage(db, READONLY)
session.DoAction("CostInitialize")
session.DoAction("CostFinalize")
set view = db.OpenView("SELECT File, Directory_, FileName, Component_, Component FROM File,Component WHERE Component=Component_ ORDER BY Directory_")
view.Execute
set record = view.Fetch
do until record is nothing
file = record.StringData(1)
directoryName = record.StringData(2)
fileName = record.StringData(3)
if instr(fileName, "|") then fileName = split(fileName, "|")(1)
wsh.echo(session.TargetPath(directoryName) & fileName)
set record = view.Fetch
loop
只是將路徑添加到您的MSI文件。
告訴我您是否需要更詳細的答案。今晚我會有更多時間詳細回答這個問題。
編輯承諾的背景(爲什麼我需要調用ConstFinalize)實際上
納文MSDN是,可以給這樣的一個明確的答案的唯一資源,但是你需要知道在哪裏以及如何從看Windows安裝程序ist恕我直言,一個非常複雜的話題。 我真的建議在MSDN installer function reference的database reference,並從Windows安裝程序SDK中的例子的混合(抱歉,找不到下載鏈接,我認爲它的某處隱藏在像3GB窗戶SDK)
首先你需要MSI的一般知識:
MSI實際上是一個關係數據庫。全部存儲在彼此相關的表格中。 (其實不是萬能的,但我會盡量保持簡單;))
該數據庫由Windows安裝程序解釋, 這將創建一個「會話」
也有一些部分是動態解決,這取決於您安裝msi的系統, 類似於環境變量的「特殊」文件夾。 例如msi有一個「ProgramFilesFolder」,其中Windows通常具有%ProgramFiles%。
所有動態的東西只存在於安裝程序會話中,而不是數據庫本身。
在你的情況下,你需要看3張桌子,照顧關係並解決它們。 '文件'表包含所有文件,'組件'表告訴你哪個文件進入哪個目錄,'目錄'表包含所有關於文件系統結構的信息。
使用SQL查詢我可以鏈接組件和文件表以查找目錄名稱(或數據庫術語中的主鍵)。
但是目錄表本身具有關係,它的結構像一棵樹。 看看這個例子目錄表(從insted的MSI拍攝)
的列是目錄,Directory_Parent和DEFAULTDIR
InstEdAllUseAppDat InstEdAppData InstEd
INSTALLDIR InstEdPF InstEd
CUBDIR INSTALLDIR hkyb3vcm|Validation
InstEdAppData CommonAppDataFolder instedit.com
CommonAppDataFolder TARGETDIR .
TARGETDIR SourceDir
InstEdPF ProgramFilesFolder instedit.com
ProgramFilesFolder TARGETDIR .
ProgramMenuFolder TARGETDIR .
SendToFolder TARGETDIR .
WindowsFolder_x86_VC.1DEE2A86_2F57_3629_8107_A71DBB4DBED2 TARGETDIR Win
SystemFolder_x86_VC.1DEE2A86_2F57_3629_8107_A71DBB4DBED2 WindowsFolder_x86_VC.1DEE2A86_2F57_3629_8107_A71DBB4DBED2 System
的directory_parent它鏈接到一個目錄。 DefaultDir包含實際名稱。 你現在可以自己解決樹,並替換所有特殊的文件夾(在VBScript將是非常繁瑣的)... ...
...或讓Windows安裝程序處理,就像安裝msi時一樣。 現在我必須介紹一個新事物:操作(和序列): 運行(安裝,刪除,修復)msi時執行定義的操作列表。有些動作只是收集信息,有些則會改變實際的數據庫。
有關於各種事物的動作(稱爲序列)列表中的MSI可以做, 像一個序列用於安裝(稱爲InstallExecuteSequence),一個用於從用戶收集信息(MSI的UI:InstallUISequence)或一個爲adminpoint安裝(AdminExecuteSequence)。
在我們的案例中,我們不想運行整個序列(這可能會改變系統或者花費很長時間), 幸運的是,Windows安裝程序讓我們運行單個操作而無需運行整個序列。 閱讀reference of the directory table on MSDN(備註部分),你可以看到你所需要的操作:
Directory resolution is performed during the CostFinalize action
所以把這種結合在一起的腳本更容易閱讀 *打開MSI文件 *「解析」它(提供會議) *查詢組件和文件表 *運行CostFinalize行動解決目錄表(不運行整個MSI) *與TARGETPATH功能
BTW得到解決的路徑我通過瀏覽安裝程序中發現的TARGETPATH功能參考MSDN 我也注意到CostInitialize不是必需的。它僅在需要獲取文件的sourcePath時才需要。
我希望這一切都更清晰,它很難解釋,因爲它花了我就像是一年半來了解它自己;)
和關於PhilmEs回答: 是有更多的影響到的分辨率目錄表,就像自定義操作一樣。請記住管理安裝可能會導致不同的導演(例如,因爲不同的序列可能會執行不同的自定義操作)。 組件有條件,所以可能根本沒有安裝文件。我很確定InstEd並沒有考慮自定義操作。
所以是的,沒有100%的解決方案。也許一切都是必要的。
Weberik,你是一個天才!這正是我所追求的。我想我明白你在那裏做表的關係。儘管在運行腳本時觸發了MSI。有沒有辦法避免這一點。你能否提供參考資料(除MSDN以外,因爲它超出了我的頭)或者你爲什麼使用costInitialize和costFinialize的原因? –