24

Following directory setting works perfectly for me.

<Directory Id='TARGETDIR' Name='SourceDir'>
  <Directory Id="ProgramFilesFolder">
    <Directory Id='INSTALLDIR' Name='MyApp'/>
  </Directory>
</Directory>

However, when I tried changing "ProgramFilesFolder" to "LocalAppDataFolder", I got lots of error when using light to link and generate my msi:

D:\runGroup.wxs(53) : error LGHT0204: ICE38: Component cmpA5561BE36D80EB58252E69DDA0C2FF8C installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file. D:\main.wxs(38) : error LGHT0204 : ICE64: The directory INSTALLDIR is in the user profile but is not listed in the Remove File table.

Looks like "LocalAppDataFolder" is not acceptable for WiX, while I believe it is one of the system folder properties which defined in here.

What am I supposed to use for LocalAppData folder?

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
Deqing
  • 14,098
  • 15
  • 84
  • 131
  • 1
    My advice: don't install to any userprofile folder at all. Install to [ProgramFilesFolder] and allow the operating system to do any redirecting. Each OS could do this differently and your "under the hood fixes" will undoubtedly backfire. If the folder isn't redirected by the OS, MSI reference counting should be able to take care of several installations for different users to the same folder. Just make sure you don't have any read/write files that you modify in the folder. Your installation folder should be read/only. Don't fight Windows's idiosyncrazies - it bites back with a vengeance. – Stein Åsmul Aug 26 '12 at 23:05
  • The problem here is, I don't know how to let [ProgramFilesFolder] redirect to the place it should be for per-user installation. That's why I had to find out workaround. – Deqing Aug 27 '12 at 07:42
  • Yes, and you shouldn't redirect it at all :-). Windows might redirect you yet again, and in different ways on Vista, Windows 7, Windows 8 etc... Windows Installer is dangerous to fight with - it fights back. You can still install to [ProgramFilesFolder] even for a per user install, and some Windows versions might automatically redirect it, others might install to ProgramFilesFolder. Don't mess with this, just let it work the way Windows dictates. – Stein Åsmul Aug 27 '12 at 23:17
  • 16
    We need to build a msi for per-user installation on Win 7 without requesting admin privilege. It's tested that in my Win 7 the `[ProgramFilesFolder]` is resolved as `C:\Program Files (x86)`, which must need admin privilege, that doesn't meet our requirement. – Deqing Aug 28 '12 at 05:42

4 Answers4

13

I converted an application from being a perMachine install to be a perUser install. In order to properly convert the install I had to add a registry key for each of the components I have.

Originally I had the following:

<Component Id="C.MyExe">
  <File Id="Fi.MyExe" Name="$(var.MyExe.TargetFileName)" Source="$(var.MyExe.TargetPath)" DiskId="1">
    <Shortcut Id="SC.StartMenu"
              Directory="D.ApplicationMenuDir"
              Name="$(var.AppName)"
              WorkingDirectory="INSTALLDIR"
              Icon="MY_ICON.ico"
              IconIndex="0" 
              Advertise="yes"
      />
      ...

When I moved the exe component to the user install I had to do something like this:

<Directory Id="LocalAppDataFolder" Name="AppData">
  <Directory Id="MyAppDirectory" Name="$(var.AppName)">
    <Component Id="C.MyExe" Guid="{MY_GUID}">
      <CreateFolder />
      <RemoveFolder Id="RemoveMyAppDirectory" On="uninstall" />
      <RegistryKey Root="HKCU" Key="Software\MyCompany\MyApp">
        <RegistryValue Name="MainExe" Value="1" KeyPath="yes" Type="integer" />
      </RegistryKey>
      <File Id="Fi.MyExe" Name="$(var.MyExe.TargetFileName)"
          Source="$(var.MyExe.TargetPath)" DiskId="1" Checksum="yes">
      </File>
    </Component>
   ...

The most important part is that you will have to add a registry key which points to HKEY_CURRENT_USER. I added a registry value for each component which indicates that the component is installed.

I also had to remove the following: Advertise="yes".

tronda
  • 3,902
  • 4
  • 33
  • 55
  • 1
    I was told that you can ignore ICE38 as that's only valid for mixed per-user/per-machine locations and not valid for a pure per-user install. See [here](http://stackoverflow.com/a/21715783/623561). – Wes Feb 18 '14 at 14:39
3

I had this problem recently. I wanted to convert my installer from per-machine to a per-user but was getting ICE38. I asked on wix-users and one opinion was that you can ignore ICE38 because that was meant as a check for per-machine installs.

See the discussion at wix-users.

Since that is the case, ICE38 is (in my opinion) incorrect and you will want to ignore it. ICE38 implies you are installing per-user resources in the context of a per-machine installation but never verifies that this is so.

Actually authoring a per-user install requires that you ignore ICE38 because it won't ever be accurate for that world.

[Edit] Looks like you got help here.

From Peter Shirtcliffe:

This is my own, admittedly inexpert, understanding of per-user installations:

Installing to subdirectory of LocalAppDataFolder is perfectly OK in a per-user MSI. Because of certain scenarios relating to roaming users, you need to add components containing elements for any directories you create under LocalAppDataFolder. That's why ICE64 is appearing.

The ICE38 error is slightly misleading: since you have a per-user installation, it's safe to ignore as long as the user cannot pick an alternative installation location that is common to all users. ICE38 is checking for the situation where multiple users all install the same component to the same path.

Just posting to help other people (like me).

dwj
  • 3,443
  • 5
  • 35
  • 42
Wes
  • 486
  • 3
  • 15
2

Ok, just found that we can do it by overwriting "ProgramFilesFolder":

<SetProperty Id="ProgramFilesFolder" Value="[LocalAppDataFolder]" Before="CostFinalize"><![CDATA[NOT Privileged]]></SetProperty>

Another thing to do is, in <Package> we need to set InstallPrivileges to limited.

Well, I can see no reason why "ProgramFilesFolder" can be used directly while "LocalAppDataFolder" can't.

Deqing
  • 14,098
  • 15
  • 84
  • 131
  • Because you don't need to do this. It automatically redirects on Win7. – Christopher Painter Aug 25 '12 at 14:43
  • The ProgramFilesFolder is not redirecting in my Win7. I tried InstallPrivileges with both 'limited' and default value, all set the %ProgramFilesFolder% to `C:\Program Files (x86)`. How do I trigger this redirecting? And another question, note that in WixUI_Advanced, it explicitly set install path for per-user to %LocalAppData%\Apps\ProgramName. So which is the offically stated version of a program should be installed to for per-user? `%LocalAppData%\Apps`, or `%LocalAppData%\Programs`? – Deqing Aug 26 '12 at 07:54
  • 1
    Deqing, this solution looks dangerous - I am surprised Windows Installer will actually let you do it. – Stein Åsmul Aug 27 '12 at 23:18
  • @Glytzhkof If you look at WixUI_Advanced's code you will find it also set install path to %LocalAppData% for per-user. – Deqing Aug 28 '12 at 05:32
  • I added a comment to tronda's answer. You can use %LocalAppData% direct. Just ignore ICE38 in your project. I was told ICE38 is invalid for a per-user install. See my answer. – Wes Feb 18 '14 at 15:08
2

Are you installing per-user or per-machine? Also, what OS versions are you targetting? You might want to read:

Authoring a single package for Per-User or Per-Machine Installation context in Windows 7

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • I'm installing per-user, that's why I need LocalAppData in the directory structure. And it will be installed on Win7. For me the only way to do is to use `SetProperty` as I described before. – Deqing Aug 25 '12 at 03:39
  • According to that article, Per-User installs on Win7 using ProgramFilesFolder will automatically redirect to LocalAppData\Programs. Does this not work for you? – Christopher Painter Aug 25 '12 at 14:35
  • I just created a test per-user install using InstallShield and set it up using [ProgramFilesFolder]My Company Name\My Product Name and sure it enough it installed to C:\Users\chrpai\AppData\Local\Programs\My Company Name\My Product Name – Christopher Painter Aug 25 '12 at 14:42
  • I'm not using InstallShield to set up my project. Maybe it will help understanding if you post key code of the wxs which generated by InstallShield. – Deqing Aug 26 '12 at 07:56
  • InstallShield doesn't generate wxs. (What a freaking shame though.) InstallShield and WiX both generate Windows Installer databases. Therefore the underlying concepts are the same. I have a few things to do today but I'll try to post a sample tonight. – Christopher Painter Aug 26 '12 at 13:55