How do I fix the upgrade logic of a wix setup after changing InstallScope to “perMachine”

后端 未结 5 737
孤独总比滥情好
孤独总比滥情好 2020-12-05 20:25

We use wix to create setups for our application. For the case where the user has already installed an older version of our application, we do a major upgrade with the MajorU

相关标签:
5条回答
  • 2020-12-05 20:29

    I implemented Mike Fuchs approach, and while it did technically work (aka install functioned as expected), the program did not appear in APR for other users.

    In thinking this over, it makes sense because how would the installer know that all per-user installs were removed/updated to the new perMachine version.

    0 讨论(0)
  • 2020-12-05 20:30

    Sadly, the Windows Installer doesn't support that. Some process outside your package (a bootstrapper/chainer?) will have to manage the upgrade from per-user to per-machine.

    0 讨论(0)
  • 2020-12-05 20:37

    Starting out with per-machine configuration.

    <Property Id="ALLUSERS" Value="1" />
    

    This will run an automatic per-machine check (if you have the MajorUpgrade element working, I presume), that does not pick up the previous per-user install:

    Action start 15:46:35: FindRelatedProducts.
    MSI (c) (D0:0C) [15:46:35:496]: FindRelatedProducts: current install is per-machine.  Related install for product '{0C6604FB-58EC-48B9-8259-5871EFDADEB9}' is per-user.  Skipping...
    MSI (c) (D0:0C) [15:46:35:496]: FindRelatedProducts: current install is per-machine.  Related install for product '{0C6604FB-58EC-48B9-8259-5871EFDADEB9}' is per-user.  Skipping...
    

    So before install, make sure you run another FindRelatedProducts call for products that have been installed in user scope (e.g. like this):

    <!-- temporarily switch to per-user install scope-->   
    <Publish Dialog="MyWelcomeDlg" Control="Next" Property="ALLUSERS" Value="{}">1</Publish>
    <!-- find related products that have been installed per-user -->
    <Publish Dialog="MyWelcomeDlg" Control="Next" Event="DoAction" Value="FindRelatedProducts">1</Publish>
    <!-- switch back to per-machine install scope-->
    <Publish Dialog="MyWelcomeDlg" Control="Next" Property="ALLUSERS" Value="1">1</Publish>
    

    This in turn finds the per-user install:

    Action start 15:46:36: FindRelatedProducts.
    FindRelatedProducts: Found application: {0C6604FB-58EC-48B9-8259-5871EFDADEB9}
    MSI (c) (D0:88) [15:46:36:716]: PROPERTY CHANGE: Adding WIX_UPGRADE_DETECTED property. Its value is '{0C6604FB-58EC-48B9-8259-5871EFDADEB9}'.
    MSI (c) (D0:88) [15:46:36:716]: PROPERTY CHANGE: Adding MIGRATE property. Its value is '{0C6604FB-58EC-48B9-8259-5871EFDADEB9}'.
    

    Existing products will be removed no matter in which check they are found.

    Action start 15:46:41: RemoveExistingProducts.
    RemoveExistingProducts: Application: {0C6604FB-58EC-48B9-8259-5871EFDADEB9}
    

    On a side note: This does not circumvent a basic difficulty that arises when you have dual-purpose installers: User1 on the machine might install in per-user scope, then later User2 installs per-machine. User1 will see both installs in his programs/features table, and I do not know which one takes precedence. So consider going with per-machine installs only.

    0 讨论(0)
  • 2020-12-05 20:37

    You can use this technique to detect per-user installation from per-machine install: http://www.mail-archive.com/wix-users@lists.sourceforge.net/msg35197.html

    0 讨论(0)
  • 2020-12-05 20:42

    This finds both existing perUser and/or perMachine installs. And forces the new install to a perMachine install (obviously logic to make that conditional could be applied as you wished). This works when run as an ordinary install and when installed silently under LocalSystem (silent upgrades). Keep in mind, it can only find a perUser install when running as that user.

    Create a custom action (in DLL)

    #pragma comment(linker, "/EXPORT:RunFindRelatedProducts=_RunFindRelatedProducts@4")
    extern "C" __declspec(dllexport) UINT __stdcall RunFindRelatedProducts(MSIHANDLE a_hInstall)
    {
    MsiSetProperty(a_hInstall, "ALLUSERS", "1");
    MsiDoAction(a_hInstall, "FindRelatedProducts");
    MsiSetProperty(a_hInstall, "ALLUSERS", "");
    MsiDoAction(a_hInstall, "FindRelatedProducts");
    MsiSetProperty(a_hInstall, "ALLUSERS", "1");
    return ERROR_SUCCESS;
    }//end function
    

    Then "replace" the standard FindRelatedProducts with the custom action

    <InstallUISequence>
      <FindRelatedProducts>0</FindRelatedProducts>
      <Custom Action="RunFindRelatedProducts" Before='FindRelatedProducts'>NOT Installed</Custom>
    </InstallUISequence>
    <InstallExecuteSequence>
      <FindRelatedProducts>0</FindRelatedProducts>
      <Custom Action="RunFindRelatedProducts" Before='FindRelatedProducts'>NOT Installed</Custom>
    </InstallExecuteSequence>
    
    0 讨论(0)
提交回复
热议问题