2009-04-15 90 views
1

作爲隨訪至this question和閱讀後羅布Mensching的blog post一個從this answer提及,似乎我試圖用的MSIZap做到這一點的方式是一個壞主意我在測試中遇到了一些問題。如何解決一個拙劣的MSI安裝程序,將無法卸載

在他之下,他會做什麼不同的崗位上,他說:

與數據建立一個解決方案。 I 期望可以構建新的MSI以解決這些問題 。然後你發送 的修復和說明出來的所有 與問題。它會 可能類似 recache /重新安裝(msiexec/fv, 支持的交換機)頂部 有問題的安裝,然後卸載。 通過這種方式,機器保持已知的 狀態,並且增量設置 得到改善。

如何構建這樣一個MSI?我使用WiX的,問題是卸載過程試圖後,因爲它InstallFinalize後安排它被移除運行exe文件。 (忘了指定,它只能運行在安裝無法卸載)

回答

0

如果MSI只是不會卸載你就可能需要使用MSI ZAP。它不會刪除任何文件,但可以使用Orca查看MSI中所有文件的列表並手動刪除它們。

2

根據卸載時的問題類型以及如何部署它,完全可以編寫腳本並部署它以編輯機器上緩存的MSI以解決問題。您可以遍歷C:\ Windows \ Installer \文件夾中的MSI以查找產品的一個(打開它們並讀取摘要信息)

一旦找到需要的那個,您可以修改表直接固定在你引入了任何問題(即禁止在卸載等自定義操作)下一次卸載被稱爲不會發生問題。

資源:
Windows Installer SQL Reference
Windows Installer Automation Interface Reference

包括示例腳本,我要指出,這主要是爲了說一個內部部署的應用程序不是真正的東西,你可以發送給客戶的修復,但其可能創建一個二進制文件做同樣的事情,並把它包含在說一個setup.exe,其中二進制揭開序幕先清理並刪除以前的卸載,然後放下新的,或者只是送出去的二進制修復卸載問題。

Option Explicit 

Dim objFS, objShell 
Dim objFolder, objFiles, objFile 
Dim objInstaller 
Dim installerPath, titleToFind 
Dim queries 

Const msiOpenDatabaseReadOnly = 0 
Const msiOpenDatabaseTransact = 1 

Set objInstaller = CreateObject("WindowsInstaller.Installer") 

Set objShell = CreateObject("WScript.Shell") 
installerPath = objShell.ExpandEnvironmentStrings("%SystemRoot%") & "\Installer\" 

'Set the title you want to use for comparison 
titleToFind = "Sample" 
' Define the queries you wish to run against the database if found 
queries = Array( "UPDATE `InstallExecuteSequence` SET `Condition` = 'NOT Installed' WHERE `Action` = 'SampleAction'", _ 
        "DELETE FROM `InstallExecuteSequence` WHERE `Action` = 'SampleAction'") 

Set objFS = CreateObject("Scripting.FileSystemObject") 
On Error Resume Next 
If (objFS.FolderExists(installerPath)) Then 
    Set objFolder = objFS.GetFolder(installerPath) 
    Set objFiles = objFolder.Files 

    For Each objFile in objFiles 
     If (StrComp (Right(objFile.Name, 4), ".msi") = 0) Then 
      If (CheckMSI (installerPath & objFile.Name, titleToFind)) Then 
       UpdateMSI (installerPath & objFile.name) 
       Exit For 
      End If 
     End If 
    Next 
End If 

Set objFS = Nothing 
Set objShell = Nothing 
Set objFile = Nothing 
Set objFiles = Nothing 
Set objFolder = Nothing 
Set objInstaller = Nothing 

' Check if the title in the MSI matches the one you are looking for 
Function CheckMSI (msiPath, title) 
    Dim objDatabase, objSummary 
    Dim msiTitle 
    Set objDatabase = objInstaller.OpenDatabase (msiPath, msiOpenDatabaseReadOnly) : CheckError 
    Set objSummary = objDatabase.SummaryInformation(0) 

    msiTitle = objSummary.Property(2) 

    If (StrComp (msiTitle, title) = 0) Then 
     CheckMSI = true 
    Else 
     CheckMSI = false 
    End If 

    Set objSummary = Nothing 
    Set objDatabase = Nothing 
End Function 

' Loop though the queries specified above and execute them against the MSI 
Function UpdateMSI (msiPath) 
    Dim objDatabase 
    Dim objView 
    Dim query 

    Set objDatabase = objInstaller.OpenDatabase(msiPath, msiOpenDatabaseTransact) : CheckError 
    For Each query in queries 
     Set objView = objDatabase.OpenView (query) : CheckError 
     objView.Execute : CheckError 
    Next 
    objDatabase.Commit 

    Set objView = Nothing 
    Set objDatabase = Nothing 
End Function 

Sub CheckError 
     Dim message, errRec 
     If Err = 0 Then Exit Sub 
     message = Err.Source & " " & Hex(Err) & ": " & Err.Description 
     If Not installer Is Nothing Then 
      Set errRec = installer.LastErrorRecord 
      If Not errRec Is Nothing Then message = message & vbLf & errRec.FormatText 
     End If 
     Fail message 
End Sub 

Sub Fail (message) 
    WScript.Echo message 
    WScript.Quit 2 
End Sub 
+0

任何鏈接或資源如何做到這一點? – Davy8 2009-05-01 15:10:05