Archive: MultiUser.nsh - Not possible to run installer without admin privileges?


MultiUser.nsh - Not possible to run installer without admin privileges?
  Hi,

the installer I am creating should run on a per user basis. So no admin privileges should be required and the program should always be installed for the current user.

Therefor I use the MultiUser.nsh with the following settings:


# other options would be: Admin, Power, Highest

>!define MULTIUSER_MUI
>!define MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
>
And insert the macro in the .onInit function:

insertmacro MULTIUSER_INIT 

>
But it doesn't seem to work as expected. I am running Windows 7 Ultimate 32Bit.

Here is the list of problems, things I do not (fully) understand:
- When I execute the installer file it always prompts for running with admin privileges!?

- For showing an installed program in the Windows programs list (for modify/repair/uninstall) it is AFAIK necessary that there is a RegKey in 'Software\Microsoft\Windows\CurrentVersion\Uninstall\'. But this RegKey doesn't exist? (at least it is not shown) in HKCU for a standard user!? And as my installer prompts for admin privileges, the current user is set from the standard user (who started the installer) to the user from whom you granted the admin privileges. As a logical result my RegKeys are written to 'HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\' of the user with the admin privileges (and not as intended to the one of the standard user).

In the end I cannot install the program for standard user at all, because all CURRENT USER settings are done for the user with the admin privileges.

It is a bit hard to describe for me, but I hope you'll get the point?

Did anybody encounter same problems?
Or what do I have to do to run the installer without the need of admin privileges?

Help is very much appreciated!

Thanks,

Gunther

After doing some more research I have the following questions:

- Windows Vista and 7 always require Admin privileges to install an application, right?
- On Vista a per user installation is not possible (always installed as per machine), right?
See
http://technet.microsoft.com/en-us/l...8WS.10%29.aspx and
http://blogs.msdn.com/b/windows_inst...windows-7.aspx

The needed Reg Subkey for the uninstall infos does not exist in HKCU - just in HKLM, right?

And when try to install as a standard user you have to grant Admin privileges and if you do a per user installation Regkeys in HKCU are those of the user with the Admin privileges and not the ones of the standard user?

AFAIK the answers to all of the above questions is "Yes".
And if so, that means that a per user installation for a standard user isn't possible at all!
Because it is not possible to write any Regkey to the standard user's HKCU (despite of all other problems).

Would be nice if someone can confirm this or tell me what to do to write an installer script for a per user installation (on Win Vista + 7).

And how about older Windows versions like 98, 2000 and XP?

Thanks,

Gunther


There is nothing wrong with putting uninstall info in HKCU (Well, it does not work on < Win2000)
When doing a per user install, you MUST use RequestExecutionLevel user and only write to HKCU and install the application in $localappdata\programs\yourapp

(I have never really looked at MultiUser, but I believe it is broken)


Anders,

Originally posted by Anders
There is nothing wrong with putting uninstall info in HKCU (Well, it does not work on < Win2000)
But the Subkey does not exist in HKCU. So how will you put uninstall info there?
MS says on one of the sites I linked above that the uninstall info should (has to be) put in HKLM. That's maybe (one) reason why always need Admin privileges for install?

BTW: Is there an equivalent for Win 98?

When doing a per user install, you MUST use RequestExecutionLevel user and only write to HKCU and install the application in $localappdata\programs\yourapp
I am a little bit confused.
http://nsis.sourceforge.net/Docs/MultiUser/Readme.html says nothing about a level "user" - only "Standard".
But anyway - I tried both with the same result. I always need Admin privileges on Win 7!?

And I use "SHCTX" which should point to HKCU.

(I have never really looked at MultiUser, but I believe it is broken)
In which way?
And what would you suggest to get an installer that needs no Admin privileges?

Thanks,

Gunther

Originally posted by Netsurfer24
I am a little bit confused.
http://nsis.sourceforge.net/Docs/MultiUser/Readme.html says nothing about a level "user" - only "Standard".
But anyway - I tried both with the same result. I always need Admin privileges on Win 7!?
user == standard with the multiuser header (why it was done like that is beyond me as it just makes it more confusing when compared to using RequestExecutionLevel directly.

i think i have to agree with anders about it being broken as what you're experiencing is the same thing we've seen with the Winamp Backup Tool (written in NSIS) when using any account other than a standard user account - causes elevation all of the time even when it's not required.

how to fix it though i'm not too sure as my NSIS skills are really rusty now though i'm preferring to either make a new header which just what is needed for the tool being made or just do things in a more basic / direct manner than what the header currently tries to wrap up (not very well it seems).

Originally posted by Netsurfer24
And what would you suggest to get an installer that needs no Admin privileges?
RequestExecutionLevel user should be what's needed to not require an elevation prompt (though i'm not 100% on that - am sure i'll be corrected)

-daz

Originally posted by Netsurfer24
But the Subkey does not exist in HKCU. So how will you put uninstall info there?
Just create the key, not all supported keys in the registry exist by default.

Originally posted by Netsurfer24
BTW: Is there an equivalent for Win 98?
Everyone is admin on Win9x, just make sure SHCTX=HKLM


This just leaves NT4, I'm not sure its Add/Remove programs dialog will show entries from HKCU

As far as MultiUser goes, if you ONLY allow single user installs, it does not make sense to use it at all.

Hi,

first of all I have to correct myself.
Using


define MULTIUSER_EXECUTIONLEVEL user 

>
did the trick and worked as expected. Means you don't need Admin privileges to run the installer.
Sorry for the confusion.
IMO it is a fault in the MultiUser Readme which reads as one has to use "Standard" which seems not to work (at least for me).

Originally posted by DrO
RequestExecutionLevel user should be what's needed to not require an elevation prompt (though i'm not 100% on that - am sure i'll be corrected)
Yes, and same for MultiUser - thanks.

Originally posted by Anders
Just create the key, not all supported keys in the registry exist by default.
Yes, now as I can start the installer as a standard user the key will be generated, so no more problem.

Everyone is admin on Win9x, just make sure SHCTX=HKLM
Shouldn't SHCTX default to it in this case?
Or do I have to check manually for the Windows version and set (override) SHCTX to HKLM?

This just leaves NT4, I'm not sure its Add/Remove programs dialog will show entries from HKCU
That will be no problem but thanks for the remark.

As far as MultiUser goes, if you ONLY allow single user installs, it does not make sense to use it at all.
I agree, but the point is that there might be older versions of the program installed which set Regkeys in HKLM. And if the user has the needed rights these keys should be removed. And I am not quite sure if I am going to use the MULTIUSER_PAGE_INSTALLMODE or not.

For having the alternative I am using the MultiUser.nsh.

Cause I can't test it myself I have to ask again:
The MU Readme says
Then, the MULTIUSER_PAGE_INSTALLMODE macro can be used just like a normal Modern UI page (this page will automatically be skipped when running Windows 95/98/Me):
and
After initialization, the variable $MultiUser.InstallMode will contain the current installation mode (AllUsers or CurrentUser).
and
On Windows 95/98/Me installation for a single user is not possible.
and last but not least
The SetShellVarContext flag (which determines the folders for e.g. shortcuts, like $DESKTOP) is automatically set depending on the installation mode.
All this sounds to me as if the MU will set the SetShellVarContext (and therefor also SHCTX) automatically. Or do I overlook something?

It is really hard to do this things right without any possibility to test it ... :(

One more question concerning Registry operations:
Is it correct that it is possible to read any Reg value with standard user rights? And that admin privileges are only needed when writing to HKLM?
How about deleting keys (same as write)?

Thanks for all your help so far! :up:

Gunther

After I have slept on the whole thing I decided to make my installer to always need Admin privileges and do a per-machine installation.

But this leads me right away to the next problem. :rolleyes:

On a Windows 7 system as soon as a standard user starts an installer which needs Admin privileges (and they are granted) the user is "switched" to the one from whom the rights were granted.

The resulting problem from this behaviour is that my installer should write an ini file during install which has to be located in the users %APPDATA% dir.

Is there any way to get the "original" user (without using UAC plugin) instead of the one with the Admin privileges?

BTW: Can anybody tell me if this behaviour also appears on Vista?

Thanks,

Gunther


Originally posted by Netsurfer24
Is there any way to get the "original" user (without using UAC plugin) instead of the one with the Admin privileges?
Not one that works, no. There exists a way however that will not always work: http://nsis.sourceforge.net/GetUserS...erFromRegistry

This also happens for Vista, yes.

if that option doesn't work 100% in all cases, couldn't it be possible to display the path that's expected and allow the user to edit it if they realise that it's not correct? only saying that as i've no idea how the installer is required to work / if the user folder is exposed anyway or if its a hidden settings folder then you can ignore me :) (either way thanks for the link MSG as i think it will at least help with some of the issues i'm trying to look into resolving at the moment).

-daz


The problem is that if you want to install an application for all users (per-machine) you need Admin privileges.

As soon as a user starts the installer who has no Admin privileges the UAC prompts for elevation. And if you confirm (enter an Admin password if required) the process runs with the Admin token.

IMHO Microsoft forget about an option to keep the original user. Actually there is no way of knwoing which user started the installer.

So if your installer needs to write some user specific config options, it can only be done for the current user who granted the Admin privileges.

That is another drawback of this damn thing called UAC. :mad:

The only possible solution I can think of at the moment is to add ie. a listbox with all user names found on the system (scan dir "Users") and let the user decide for which users to set the config options. If there is no other user found than the actual user then you can skip this step.

Gunther

Addition 1:
Another solution is the way the FileZilla installer does. Check if Admin privileges are available - if yes => choose between per-user and per-machine install. If not, install for current user.
BTW: What to look for if the application has already been installed for a user and is then re-installed for ALL users?
Do I have to delete the Regkeys or to uninstall the per-user installation (because it can't normally be located in the %ProgramDir%)?


Originally posted by MSG
Not one that works, no. There exists a way however that will not always work: http://nsis.sourceforge.net/GetUserS...erFromRegistry
Interesting approach.. but if somebody's doing that, why not use File I/O and simply write a file to one of the shared files folders, then read that from the Admin-elevated process? That should work short of something -very- odd happening?

Originally posted by Netsurfer24
IMHO Microsoft forget about an option to keep the original user. Actually there is no way of knwoing which user started the installer.

So if your installer needs to write some user specific config options, it can only be done for the current user who granted the Admin privileges.
Well that is actually by design. If you have user-specific configuration options, then those user-specific configuration options should go in the user's Local App Data location; for which you don't need Admin privileges. If you have both 'all users' and 'current user' configuration options, then that's typically addressed by the application you're installing, (e.g. copying/writing a template config file for the current user running the app) rather than its installer.

Originally posted by Animaether
Interesting approach.. but if somebody's doing that, why not use File I/O and simply write a file to one of the shared files folders, then read that from the Admin-elevated process? That should work short of something -very- odd happening?
But this would require the UAC plugin, or some manual elevation execution, because you need to execute code at the user level before elevating. That's the whole issue here.

You are very correct however that if the app needs something in user level appdata, it should be put there by the *application*, not the installer.

Ahhh okay, I see what it does now.. but you'd need to know the user's ID you're interested in first, looks like?
As far as 'run as user first, then elevate'.. I thought that was the context of the question; after elevation, how to get back to the -original- user - or at least get at their paths? If you're already running as Admin then that question becomes moot :)


Hi,

as there seems to be no other suitable way I decided to use the UAC plug-in.
The problem is that it is not very well documented.

As I understand it right, there is a second (inner) process started if the original user is not in Admin group (or Power User on XP).

So if there are two processes the outer one is always running with the original user.
Is there a possibility at the end of the installation process to close/ leave the inner process (if there is one) and write my file to the %APPDATA% dir of the original user?

Thanks,

Gunther


Originally posted by Netsurfer24
The problem is that it is not very well documented.
[...]
Is there a possibility at the end of the installation process to close/ leave the inner process (if there is one) and write my file to the %APPDATA% dir of the original user?
Sounds like a variation on one of the examples in the wiki:

CreateShortcuts

CreateShortcut "$Desktop\${APPNAME}.lnk" "$Windir\Notepad.exe"
>FunctionEnd

Section "Desktop Shortcut"
GetFunctionAddress $0 CreateShortcuts
UAC
::ExecCodeSegment $0
SectionEnd
>
Where you would replace the shortcut-creation code with file placement code.

Originally posted by Animaether
Sounds like a variation on one of the examples in the wiki:
Thanks Animaether - though I read the example I was a bit irritated by
NOTE: Syntax has changed in 0.2 alphas, everything on this page uses the old syntax
Gunther

And just the next question (I am totally confused by now) ...

How about Windows versions prior to Vista?

I want my installer to work in dual-mode (choice between per-machine and per-user installation).

So the RequestExecutionLevel is set to 'user'.
Then I use 'UAC::RunElevated'.

But if the user aborts the UAC dialog the installer continues but with a per-user installation.
And what if UAC is disabled?
Do I have to set the install type depending on the current user's rights?
Which means if the user is not an Admin I can only perform a per-user install?

On Windows XP or 2K a "Runs as Administrator" dialog is prompted to the user?
What if the user aborts this dialog?

Do I have to add WinVer.nsh and perform a Windows version check first?

And what happens on Win98?

Sorry, but I am really confused.

Gunther


Ahh, gotcha. Well you can always use the older plugin, I suppose.

For the newer one, I *think* it would be:


!insertmacro UAC_AsUser_Call Function YourFunctionName ${UAC_SYNCREGISTERS}


The ${UAC_SYNCREGISTERS} I'm not sure you need to have set (if you don't, its you'd replace it with 0 (zero)). It is one of the UAC flags that can be passed from the inner (Admin) process to the outer (User) process. There's other flags for synchronizing the stack, the path set by SetOutpath, the $INSTDIR variable and one for clearing the Error flag.

You're right that it could use some updated documentation, and abstraction for end-users, but I guess this plugin is fairly advanced territory anyway :)

After UAC::RunElevated returns, you must check if the user canceled etc

As far as OS version checking goes, it was designed so that you don't really need to check the version (When running on NT4/Win9x, everything is just called directly since there is not outer process)

I'm sorry about the current mess, the initial version of the plugin was created early in the Vista lifetime and as feature requests etc came in, the basic plugin design had to change. (I did not write most of the wiki page contents)

And yes, creating an installer that supports both current and all users modes is VERY hard.

And as a final note, wanting to access %APPDATA% of the original user when doing a all users install is a design flaw, the installer should install shared/default data somewhere and your APPLICATION should copy it to %APPDATA% during its first run...


Hi Anders,

thanks for your reply. :)

Originally posted by Anders
After UAC::RunElevated returns, you must check if the user canceled etc
OK. Upon this check (0 on success, 1223 if user aborted elevation dialog) I set my 'SetShellVarContext' for all or current user install.

As far as OS version checking goes, it was designed so that you don't really need to check the version (When running on NT4/Win9x, everything is just called directly since there is not outer process)
Yes, but mustn't I set my variable (IS_ADMIN) or the 'SetShellVarContext' to 'all'?

I'm sorry about the current mess, the initial version of the plugin was created early in the Vista lifetime and as feature requests etc came in, the basic plugin design had to change. (I did not write most of the wiki page contents)
No problem. ;)
I first downloaded version 0.2.2b and this package does not include any Readme file (found it meanwhile in the older version archive).
Also the UAC.nsh in the new version seems to be broken. When trying to compile a script, execution is aborted cause of invalid command 'UAC::_' which is used several times.

And yes, creating an installer that supports both current and all users modes is VERY hard.
I found this out ... :rolleyes:

And as a final note, wanting to access %APPDATA% of the original user when doing a all users install is a design flaw, the installer should install shared/default data somewhere and your APPLICATION should copy it to %APPDATA% during its first run...
I agree. But the point is that I am just writing the installer script (for Windows) - not the application itself. The program is cross-plattform (Win, Linux, Mac) and the author (a Linux guy) hasn't much interest in adding Windows specific code.
The program needs many config settings which are all stored in an ini file. If it does not exist on start-up it is created. This file always resides in the %APPDATA% dir of the respective user (who runs the program).
So normally if you first start the program the language of the program is set to the default one (English) and some working directory paths aren't present. Changing the programs language needs a re-start to take effect. And the missing paths lead to a messagebox on start and the user needs to go to the config settings and add the path values.
So I have added a custom page to my installer where there is a checkbox for setting the program language to the same as the installer runs at. And a DirRequest with the listbox (do you remember my other thread concerning this topic? :D) to add as many path values as desired.

But unfortunately these settings have to be in an ini file which is located in the users %APPDATA% dir.
So "cheating" a bit seems still more preferable to me as confronting the user with those messageboxes on start-up.
Or do you know another possibility to achieve the same result?

Thanks for all the help here! :up:

Gunther