2016-10-24 39 views
1

我們正在將安裝程序從Visual Studio安裝程序項目(* .vdproj)升級到WiX安裝程序。從我們的用戶角度來看,我們希望儘可能無縫地實現這一轉變。即如果他們使用* .vdproj內部版本的MSI安裝了我們軟件的1.0版本,那麼使用WiX版本中的MSI進行v2.0安裝應該覆蓋/刪除舊版本並繼續正常運行。如何使用ALLUSERS = false從* .vdproj安裝程序轉換到使用InstallScope = perMachine的WiX安裝程序

我們遇到的問題是原始* .vdproj安裝程序將軟件安裝爲「ALLUSERS = false」,而現在使用WiX我們想使用InstallScope =「perMachine」(即「ALLUSERS = true」)。

我們使用引導式WiX安裝程序,其中鏈中的第一個元素處理.Net Framework安裝(如有必要),第二個元素是我們產品的MSI安裝程序。

這是我們的第一次嘗試升級代碼看起來像[1][2]

<MajorUpgrade DowngradeErrorMessage="A newer version of ... is already installed." /> 

<Upgrade Id="{UPGRADE-CODE-OF-OLD-INSTALLER}"> 
    <UpgradeVersion OnlyDetect="no" Property="OTHER_STUFF_FOUND" Minimum="0.0.0" /> 
</Upgrade> 

如果我們在新的WiX的安裝程序設置InstallScope =「每用戶」,那麼這將工作所需但是如果我們設置InstallScope = 「perMachine」然後卸載失敗,此錯誤記錄:

MSI (c) (04:10) [23:18:49:626]: FindRelatedProducts: current install is per-machine. Related install for product '{PRODUCT-CODE-OF-OLD-INSTALLER}' is per-user. Skipping... 

一些研究,我們瞭解到,這是一個已知的問題後,和那麼簡單,因爲什麼上面寫的是一個解決方案是不可能的因爲... e微軟安裝程序阻止上下文切換(即從perUser到perMachine)。

問題是:我們該如何以穩健的方式處理此升級?目前我們沒有工作解決方案。

我能想到的幾個選項,但想看看,如果人們有更好的答案,哪個選項是最好的建議,或者對如何實現這些上市方案的一個建議:

  1. 使用自定義操作來手動卸載舊軟件,或向用戶提供警告,以手動卸載舊版本並終止安裝。如果我們知道舊安裝程序的升級代碼,我們應該能夠搜索註冊表以查看舊軟件是否已安裝?當我查看了
  2. 是否可以使用第二個WiX MSI安裝程序作爲InstallScope =「perUser」運行並全權負責刪除舊的安裝?
  3. 我找到了這個解決方案[3],但是因爲我們使用Bootstrapped安裝程序,MSI項目中的標籤沒有執行,所以它不適用於我們。
  4. 改變我們的新的WiX的安裝程序「每用戶」,並處理這個問題在未來的一段時間(不理想的解決方案)

關於卸載舊的每用戶安裝。如果與最初用於每個用戶安裝的用戶相比,如果有其他用戶登錄,似乎可能會出現問題。這裏有什麼問題需要注意嗎?

UPDATE

我曾嘗試使用CustomAction中,我使用了升級代碼,以查看是否安裝了我們的軟件的早期版本調用MsiEnumRelatedProducts的方法,然後調用

msiexec /X {PRODUCT-CODE-FOUND-USING-MsiEnumRelatedProducts} \q 

卸載舊版本。然而,這不起作用,因爲看起來MSI使用Mutex鎖來確保一次只能執行一次MSI操作。

回答

1

我會回答我自己的問題。

在端我創建用下面的代碼一個CustomInstallerAction:

public class CustomActions 
{ 
    [CustomAction] 
    public static ActionResult CustomAction1(Session session) 
    { 
     session.Log("Begin CustomAction1"); 

     StringBuilder sbProductCode = new StringBuilder(39); 
     uint iIndex = 0; 

     try 
     { 
      while (0 == MsiEnumRelatedProducts("YOUR MSI GUID HERE", 0, iIndex++, sbProductCode)) 
      { 
       session.Message(InstallMessage.Error, new Record(1) { FormatString = "Setup has detected a version of the software from 2016 or earlier. Please manually uninstall this version using the Control Panel before installing this new version." }); 

       return ActionResult.UserExit; 
      } 
     } 
     catch (Exception ex) 
     { 
      session.Log("2: " + ex.ToString()); 
     } 
     return ActionResult.Success; 
    } 


    public static string EnumRelatedProducts(string UpgradeCode, uint Index) 
    { 
     StringBuilder ProductCode = new StringBuilder(); 
     UInt32 rc = MsiEnumRelatedProducts(UpgradeCode, 0, Index, ProductCode); 
     Console.WriteLine("Returned"); 
     if (rc != 0) 
     { 
      return string.Empty; 
     } 

     return ProductCode.ToString(); 
    } 

    [DllImport("msi.dll")] 
    private static extern uint MsiEnumRelatedProducts(
     string lpUpgradeCode, 
     uint dwReserved, 
     uint lProductIndex, 
     StringBuilder lpProductBuf); 

} 

並補充在維克斯安裝程序執行以下操作:

<Binary Id="****" src="..\***\bin\$(var.Configuration)\***.CustomInstallerAction.CA.dll" /> 

<CustomAction Id="RemoveVDPROJVersions" Return="check" Execute="immediate" BinaryKey="***.CustomInstallerAction.CA.dll" DllEntry="CustomAction1" /> 

<InstallExecuteSequence> 
    <Custom Action="RemoveVDPROJVersions" Before="LaunchConditions"> 
    NOT Installed AND NOT REMOVE 
    </Custom> 
</InstallExecuteSequence> 
相關問題