3
votes

I have the below Wix XML code that I have written for Single Package Authoring. The problem is when "Install for all unders of this machine" mode is selected in the UI(WixUI_Advanced), the default location that shows up in the UI is "C:\Users\XXXX\AppData\Local\Programs\MyApp\ ". How can I change this, so that the default location is ..\Program Files (x86)\MyApp....

If I change <Property Id="MSIINSTALLPERUSER" Value=" "/>, then the default location is ..\Program Files(x86).., but the per user does not work due to lack of admin privileges.

Much appreciated.

<Wix    xmlns="http://schemas.microsoft.com/wix/2006/wi"
        xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
        xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">


    <!--Product Information-->
    <Product Id="*"
               Name="$(var.ApplicationName)"
               Language="1033"  Version="!(bind.FileVersion.$(var.ExecutableName))"  Manufacturer="$(var.ManufacturerName)"
               UpgradeCode="33bc2348-****-****-****-ebcde0d14afe">

        <!--MSI Package Information-->
        <Package InstallerVersion="500"
                   Compressed="yes" />


        <!--Single Package Authoring-->
        <Property Id="MSIINSTALLPERUSER" Value="1"/>
        <Property Id="ALLUSERS" Value="2"/>

        <!--Upgrade Information-->
        <MajorUpgrade DowngradeErrorMessage="A newer version of $(var.ApplicationName) is already installed." />

        <MediaTemplate EmbedCab="yes" />

        <!--Application Features-->
        <Feature Id="CoreFeature" Title="$(var.ApplicationName)" Level="1">
              <ComponentGroupRef Id="ProductComponents" />
              <ComponentRef Id="ApplicationShortcut" />
              <ComponentRef Id="RegisterApplicationAutoStart" />
        </Feature>

        <!--Required .NET Framework for the Application-->
        <PropertyRef Id="NETFRAMEWORK35" />
        <Condition Message="This application requires Microsoft .NET Framework 3.5 or greater. Please install the .NET Framework then run this installer again.">
            <![CDATA[Installed OR NETFRAMEWORK35]]>
        </Condition>

        <!--Advanced UI-->
        <Property Id="ApplicationFolderName" Value="$(var.ApplicationName)" />
        <Property Id="WixAppFolder"          Value="WixPerMachineFolder" />

        <UIRef Id="WixUI_Advanced"/>

        <InstallExecuteSequence>
                  <Custom Action="LaunchApplication" After="InstallFinalize">NOT Installed</Custom>     
        </InstallExecuteSequence>

    </Product>


    <Fragment>
        <!-- Define the Target Directory.  The individual files will be filled in via a Heat generated fragment. -->
      <Directory Id="TARGETDIR" Name="SourceDir">
        <!--Define the directory when the application will be installed-->
          <Directory Id="ProgramFilesFolder">
                <Directory Id="APPLICATIONFOLDER" Name="$(var.ApplicationName)" />
          </Directory>
    </Fragment>


    <Fragment>
        <Component Id="RegisterApplicationAutoStart" Directory="ApplicationProgramsFolder" Guid="*">
            <RegistryValue Root="HKMU"
                             Key="Software\Microsoft\Windows\CurrentVersion\Run"
                             Name="$(var.ApplicationName)"
                             Type="string"
                             Value="[APPLICATIONFOLDER]$(var.ExecutableName)"
                             KeyPath="yes" />
        </Component>
    </Fragment>

</Wix>
4

4 Answers

1
votes

Please follow the link below http://wixtoolset.org/documentation/manual/v3/wixui/dialog_reference/wixui_advanced.html

For a per-machine installation, the default installation location will be

[ProgramFilesFolder][ApplicationFolderName] 

and the user will be able to change it in the setup UI.

For a per-user installation, the default installation location will be

[LocalAppDataFolder]Apps[ApplicationFolderName] 

and the user will not be able to change it in the setup UI.

you can set the per user to 0 to enforce installation per machine - or in Program files

<WixVariable Id="WixUISupportPerUser" Value="0" />

For per-machine installation you will need admin privileges, if the user will not have admin privileges, he only has access to his local app data folder, hence that location cannot be changed.

1
votes

If you want to install to the Program Files folder then you are required to be administrator. Limited users cannot create or update files in that folder, and running an MSI install does not break security just because it's an install. So the answer is that you cannot install to ProgramFiles unless you cause the MSI to ask for elevated privileges. Your question is essentially "how can a limited user break security by adding or replacing files in the Program Files folder", and there's no way to answer that.

Does your app require elevated privileges to run? Does it have an elevation manifest? If the answer is yes, then I suspect you're stuck with the requirement that elevated privileges are also needed to install it.

1
votes

I included the below line in the WiX installer that fixed my issue.

 <SetDirectory Id="ProgramFilesFolder" Value="C:\Program Files (x86)\"></SetDirectory>

This changed the value of ProgramFilesFolder that was being set to C:\Users\XXX\AppData\Local..... to C:\Program Files (x86) for per machine installation.

Also the above line of code does not make any difference to per user installation and installation happens at that user folder only (as desired.)

1
votes

The OP described it perfectly. With single authoring enabled in the following way, there seems to be no way to obtain to "actual" ProgramFilesFolder at C:\Program Files (x86)\.

<Package InstallerVersion="200" ... /> <!-- do not specify InstallScope or InstallPrivileges! -->
<Property Id="ALLUSERS" Value="2" />
<Property Id="MSIINSTALLPERUSER" Value="1" />

Even if MSIINSTALLPERUSER is reset, this does not change the value of ProgramFilesFolder, it's still C:\Users\XXX\AppData\Local\Programs (I assume the folder is initialised through SHGetFolderPath at installer startup, and doesn't change thereafter).

Setting the ProgramFilesFolderexplicitly like the OP showed in his answer would work I guess, but it's an ugly hack. What worked for me in the end was to start out in 'perMachine'-Mode:

<Property Id="ALLUSERS" Value="2" />
<Property Id="MSIINSTALLPERUSER" />

Afterwards, if the installer chooses the 'perUser'-Mode, I set the variables accordingly:

<Publish Dialog="MyWelcomeDlg" Control="Next" Property="MSIINSTALLPERUSER" Value="1">1</Publish>
<Publish Dialog="MyWelcomeDlg" Control="Next" Property="ALLUSERS" Value="{}">1</Publish>

This way, the folders will be correctly set.

I consider the underlying problem to be that ProgramFilesFolder would ever get set to something in AppData, that makes little to no sense.