views:

699

answers:

3

I've written an installer using NSIS and I need it to install some files (DLLs etc.) in a standard location like C:/Program Files/App Name/. I also need to install files in the current user's Application Data directory. The problem is that when the user is not an admin on Vista I need to elevate privileges and in doing so the environment variables change so the current user now appears to be the admin user and I end up installing in the Admin user's directory instead of the actual user. You have to elevate when you start the installer so I can't grab the username and then elevate. Is there some reasonable way to figure out who the actual user is when I'm running an installer as an admin?

Edit: Unfortunately having the data copied on first run is not an option. The app won't work without the thing I'm writing to the user's directory because it's a MS Word template. My stuff WOULD NOT RUN without the template, so I MUST write the template on install and Word requires the template to be in the user's AppData dir.

+1  A: 

Look at the Windows 7 Logo Program document. It states:

Please note that in the Per- machine installations, user data must be written at first run and not during the installation as there is no correct user location to store date at time of installation.

If your application is for one user only. Then you should install to Local setting folder ( slightly different name on vista and windows 7, I think ).

Igal Serban
+1, do the OS X trick, just do these things on first execution of the application, because you can't be guaranteed that the user who ran the app is the one who installed it.
Paul Betts
Unfortunately that is not an option. The app won't work without the thing I'm writing to the user's directory because it's a MS Word template. My stuff WOULD NOT RUN without the template, so I MUST write the template on install and Word requires the template to be in the user's AppData dir.
idontwanttortfm
+2  A: 

What if another user tries to run the application? Then the files won't be available - this is a problem I battled with for many months...

The best solution I found was to take advantage of a little known (and entirely undocumented) Windows feature called Active Setup. See http://www.etlengineering.com/installer/activesetup.txt for a good description of how it works.

This is the same feature that IE uses to install per-user settings, to summarize the above link, basically you create a registry key which windows checks every time a user logs in. If the value in the HKCU key is less than the one found in HKLM, it runs your defined script/program/whatever. You install the per-user files to the program files folder, and then use the Active Setup functionality to copy them to the users profile the next time they login. If you need to ensure they're there when setup completes, then schedule a reboot when your installation completes.

PS. if using MSI instead of NSIS then you don't have to elevate when you start the installer and Vista should trigger elevation at the beginning of the Execute sequence (if the installer is designed properly - few are) - however as you're using NSIS then I'm guessing you will need to trigger elevation when the installer is run.

EDIT: Haha, my exact problem was with MS Word templates also! The solution I found for Word templates is to read the install dir from HKLM\SOFTWARE\Microsft\Windows\CurrentVersion\App Paths\Winword.exe and install to the STARTUP folder underneath the path contained in that registry key. The user will be prompted to allow the Macros to execute at first run even if it's digitally signed but it will be available for all users. Make sure to set the template to read-only as well to avoid any permissions errors later on.

sascha
This looks very cool, I'm going to set this up and see if it does everything I need to do. If so, you've been very helpful. In fact, you've been very helpful regardless of the outcome of my tests. Thanks.
idontwanttortfm
Awesome trick, thanks.
Roel
+2  A: 

All of my NSIS installers use this UAC plug-in: http://nsis.sourceforge.net/UAC_plug-in.

You can elevate to admin as soon as you launch the installer. This spawns a second instance of your installer that does all of the work. But you can make calls to code segments that will run in the original process as the user that launched the installer.

So you could have an installer section like so:

Section "Install My Program" SecMain
    ...    
    # Install files to common folders
    ...
    !insertmacro UAC.CallFunctionAsUser CopyUserWordTemplate
    ...
SectionEnd

Function CopyUserWordTemplate
    SetOutPath $LOCALAPPDATA
    File "MyWordTemplate.dot"
FunctionEnd
Kyle Gagnet