2013-07-09 110 views
2

我正在尋找使用VBScript從MSI外部解決MSI中文件的路徑,無論是否安裝(無論哪個更快)。如何解決VBScript中的MSI路徑?

我發現了一個類似的查詢使用C#,而不是和Christpher已經提供瞭解決方案,如下:How can I resolve MSI paths in C#?

我會通過同樣的痛苦,但現在反正是有實現的VBScript此使用WindowsInstaller對象,而不是通過來自MSI的SQL Tables的無數查詢來回實現相同。儘管任何方向都會受歡迎,因爲我已經嘗試過任何我能夠做的非常有限的成功嘗試。

回答

5

是的,沒有安裝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 referencedatabase 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%的解決方案。也許一切都是必要的。

+0

Weberik,你是一個天才!這正是我所追求的。我想我明白你在那裏做表的關係。儘管在運行腳本時觸發了MSI。有沒有辦法避免這一點。你能否提供參考資料(除MSDN以外,因爲它超出了我的頭)或者你爲什麼使用costInitialize和costFinialize的原因? –

2

weberik給出的腳本(衍生於MS SDK VB代碼)非常好,因爲它可以很容易地分析目錄表而無需使用自己的算法(這是一箇中等大小的工作,可以在循環或用遞歸算法)。 但是它並沒有給出所有文件的100%完美視圖,請參見下文。 腳本的方法是半動態的(可以通過其他操作進行擴展),但實際上它只提供靜態目錄結構,類似於默認的管理安裝或高級MSI查看器。

通常這已經足夠了,我們想要什麼。 但請注意,這不是100%的解決方案(以後確切知道每個文件的路徑)。這確實意味着,在某些情況下,這不會給您始終正確的路徑:

  • 您使用替換預定義目錄表條目的命令行參數。
  • MSI使用更改路徑的自定義操作。
  • 特別是不能保證每個文件都被安裝。可能有可選的條件和功能,這可能取決於安裝環境。

實際上,一個100%的解決方案非常難以實現,沒有真正的安裝。它接近重新編程幾乎整個Windows安裝程序引擎。所以簡化通常是足夠的並且被接受。

但是,您可以擴展該方法以涵蓋自定義操作,例如爲每個需要的附加操作添加一行「session.DoAction(..)」。或者包含命令行參數。

有時候可能會很棘手。 MSI的結構越簡單,就越有可能在沒有更多努力的情況下取得成功。

替代寫自己的程序: 問題是,你真正想要發現什麼,以及是否真的有必要編程它: 如果你不想寫一個自動化的每一天的MSI分析儀也許以下爲你是足夠:

第一前端:與安裝MSI「MSIEXEC /一個mysetup.msi TARGETDIR =」 C:\ mytestpath」(類似的限制如上述腳本由weberik) 如果MSI具有不使用自定義操作來改變路徑,包括忘記添加到管理員序列中(「忘記」應該被視爲99%或現有設置的正常情況:-),您將獲得文件結構,如果您使用某些特殊命令安裝「真正」爲Windows p重新定義您將很容易找到的文件夾。

如果管理安裝缺少某些文件夾,修復自定義操作(添加到管理序列)並將此場景用作主要測試用例通常是一個更好的主意。 好處是,只有你限制了管理員安裝使用的動態。順便說一句,您可以使用與實際安裝中相同的命令行參數或路徑設置自定義操作。第二個技巧:Google for InstEd工具,轉到文件或組件表,您將在調用CostInitialize/CostFinalize後,以與提到的VB腳本相同的靜態方式看到生成的MSI路徑。對於人類來說,這樣的編輯視圖可能更好。

對於自動測試和改進或準確性,您當然需要自己的程序。 對於你提到的那些片段是一個很好的起點。 :-)

其餘的人應該更容易使用兩種給定方法之一而無需編程。

+0

非常感謝您的詳細解答,Philm!總是很高興知道更多! –

相關問題