- NSIS Discussion
- More Vista / RequestExecutionLevel pitfalls
Archive: More Vista / RequestExecutionLevel pitfalls
RDaneel
15th January 2008 22:42 UTC
More Vista / RequestExecutionLevel pitfalls
I just noticed that using RequestExecutionLevel admin has the unexpected (for me, anyway) side-effect of not just changing the *privileges* of the installer BUT also of changing the *user*! :(
Specifically, I note from both observation and from the installer's own details window that the selected per-user folders and desktop are NOT those of the logged-in user, but those of the admin user going with the password Vista demanded.
This is with using $SMPROGRAMS, $DESKTOP, and leaving SetShellVarContext defaulted to [presumably] current.
The installer is NSIS 2.34, created on XP SP2, and installed on Vista RTM.
I am going to now try "RequestExecutionLevel user", but based on other comments here, I expect other troubles (like issues with $PROGRAMFILES?).
Anders
15th January 2008 23:15 UTC
Welcome to the wonderful world of Vista
The UAC plugin tries to deal with some of these issues.
http://nsis.sourceforge.net/UAC_plug-in
<Rant Type="Vista/UAC/NT/LUA">
if you require admin rights to install, you are doing a "all users" type install, so you put your files in $programfiles, uninstall info in HKLM and the shortcuts should be for all users (SetShellVarContext all)
</Rant>
RDaneel
15th January 2008 23:30 UTC
Thanks, Anders!
This looks like it may mostly work (but I am troubled by the Important Notes #3 issue), but what a ridiculous mess to have to do all this for the fairly ordinary task of installing an app... silly Vista. Sigh.
OTOH, it looks like all that is really NOT working properly with "RequestExecutionLevel user" is installing the app files to a $PROGRAMFILES subdir... does Vista have someplace else that functions as a "standard" place for app files to be placed?
Or do they just think it makes sense to force you into needing admin privileges which then make all of your per-user paths wrong? Grrr.
Anders
16th January 2008 00:08 UTC
$LOCALAPPDATA can be used for single user installs
As far as issue #3 goes, for normal folders, there should be no problem, normal users have exec rights by default for files installed by an admin (I have never had a problem with this, might be an issue in domains with tight security or something like that, dunno)
RDaneel
16th January 2008 02:46 UTC
Yes, reasonably enough, I have always used $APPDATA and friends for [per-user] data... but for executables, it has always been $PROGRAMFILES.
For some reason, I had thought their was now in Vista a per-user version (or analog) of $PROGRAMFILES - but I don't see it, now that I am forced to actually try and deal with this nasty state of affairs.
And thanks again - I at least have a way to proceed now... it just seems there could have been a better way for this all to work out. I know - their answer would no doubt be to use the MSI ecosystem, and all would be good. Sigh again.
Anders
16th January 2008 10:39 UTC
there is a per user analog (the real analog has always been $APPDATA and $LOCALAPPDATA) of $PROGRAMFILES in vista, but its a hack, and when you use RequestExecutionLevel, that gets disabled (file redirection or whatever its called). And without RequestExecutionLevel, Vista auto detects nsis installers and forces you to run it as admin. Even if you could get around that, you end up at pretty much the same place since the redirection of program files ends up in $LOCALAPPDATA\somefolder anyway
Joost Verburg
16th January 2008 16:29 UTC
The current development builds of NSIS include a new header file (MultiUser.nsh) that is designed to deal with such issues automatically. See http://nsis.sourceforge.net/Docs/MultiUser/Readme.html for details. I would appreciate tests and feedback.
Note that you can choose the "highest" execution level to allow non-admin users to install your software in $LOCALAPPDATA, while administrators can install in $PROGRAMFILES. Software in $PROGRAMFILES is be available for all users, so the shortcuts should be installed in the per-machine folders instead of the folders for the current user.
Anders
16th January 2008 20:18 UTC
I have not looked into the new MultiUser stuff, but I assume you run into the finish page run problem(runs as admin instead of logged in user on vista with standard user doing a all user install), unless you are doing some UAC magic
Joost Verburg
16th January 2008 23:46 UTC
That depends on the manifest of the application you run (i.e. what privileges it requests).
RDaneel
17th January 2008 04:07 UTC
Ummm... I am having sort of a meta-problem here. ;)
I must be missing something, because it looks like the whole Vista "install" model is seriously broken - at least for us "exe" installer types, since I still assume MS made things work a bit better for the "msi" installer case(s).
I have a shell extension which needs to get registered, and AFAIK, that means at least some entries in, e.g., HKCR and HKLM... but even if I didn't, there is still the issue of the uninstall entries, which also go to HKLM (or can I do ALL uninstall stuff in HKCU?).
So how does ANYTHING get installed without requesting Admin privileges? Once you do, you are shafted by the really crippled security model that seems unable to give you Admin privileges without making the installer BECOME an Admin - thus losing the correct meaning of "current user".
I just tried making the trivial changes to use the $LOCALAPPDATA tree to install my app's code files, did a "RequestExecutionLevel user", and did an install... which seemed to work, but had actually silently FAILED.
The app files were installed as expected, the desktop shortcut was there, and the menu entries were there - all FILE things worked fine, as expected. But since NONE of the HKCR/HKLM writes actually happened, my Shell extension was MIA, and there were no uninstall entries.
Just to be clear, I always do a "this user only" install, but have assumed (perhaps incorrectly?) that even that case still needs Registry entries written outside of HKCU.
Anyway, I am going to try and use the UAC plugin, which looks like it will probably let me install my app on Vista "properly" - but this all seems like such an ugly mess that I still feel like something is very wrong - with either my model of how installs work, or Vista, or both. :(
Anders
17th January 2008 11:36 UTC
Originally posted by Joost Verburg
That depends on the manifest of the application you run (i.e. what privileges it requests).
Not it does not.
Say user "Joe" is a standard user.
He wants to install app "Foo". Foo's installer has RequestExecutionLevel=admin, so Joe elevates with admin account "Root". If run is checked at the finish page, the Foo program is started as Root even if it has a RequestExecutionLevel=user manifest, so all its settings end up in the wrong HKCU/$appdata. The next time Joe starts Foo, all his settings from the first time he used the app are gone, since they were saved in the Root profile.
RDaneel:
Uninstall info can be stored in HKCU
This works for most shell exstensions aswell, use HKEY_CURRENT_USER\Software\Classes instead of HKCR
from win2000 and up, you can use HKEY_CURRENT_USER\Software\Classes instead of HKCR for most shell/COM stuff when doing things for a single user
Joost Verburg
17th January 2008 17:42 UTC
Right. So Foo won't be able to perform administrative actions, but the user associated to it would be the administrator that is used for the installer?
It really depends on the type of application what is the right thing to do. A system-wide configuration program should be run using the administrator account, because you don't want another UAC prompt. Most normal application should indeed run using the current Windows user account because of configuration in HKCU/$APPDATA.
I would suggest to create a header file using the UAC plug-in that allows you to run an application using the Windows user account instead of the account that is used for the installer. I don't have a Vista system available right now, but would be happy to include a contributed header file to the official NSIS package.
Anders
17th January 2008 19:55 UTC
you can't really solve this with a simple header file, all calls to Exec* needs to be changed to UAC::Exec* in the users code (the MUI code could look for some special UAC define, but that only solves the finish page problem, other possible calls to Exec* and CreateShortcut are still problematic)
Joost Verburg
17th January 2008 20:28 UTC
I don't really understand what you mean, it's not that all calls have to be replaced. As I said, there are applications that do need the administrator privileges of the installer. For most applications that are started during the installation itself this will be the case.
So a simple macro in a header file that performs the necessary UAC plug-ins call would certainly solve the issue (or is it just a single UAC plug-in command?). This allows the user to run the application using the current Windows user account whenever that is required.
What's the problem with CreateShortcut? The location is just determined by SetShellContext. Whenever a RequestExecutionLevel command is included (so Vista does not redirect shortcuts) there should be no issues.
Anders
17th January 2008 20:36 UTC
First off, for installers that use the UAC plugin, you must use RequestExectutionLevel=user since the UAC plugin has to performe the elevation, so there is never just one easy command.
as for CreateShortcut, people want it work "normally" with SetShellContext=current
Joost Verburg
17th January 2008 22:40 UTC
I think there should be a possibility for an installer with RequestExectutionLevel=admin to run an application using the current user Windows account, without using the UAC plug-in for other things. I'll have to check the details of this plug-in and the Windows API.
Regarding CreateShortcut, you mean an installer with RequestExectutionLevel=admin combined with SetShellVarContext=current? It's a bit of a weird combination. An installer that allows per-machine/per-user installation should normally use RequestExecutionLevel=highest. But there may indeed be some exceptions (a per-user application that needs a service/driver?).
We should check the behavior of other installers and change the SetShellContext=current mode if necessary (or add an additional mode).
Anders
17th January 2008 23:36 UTC
I know its a weird combination, but some users want it (They are used to the way its done on 2k/XP, but few people run as non admin there so the issue has somewhat hidden) Other things you might want to do is get the users name etc, that can be done since the UAC plugin supports calling any nsis function in the context of the current user.
When using RequestExectutionLevel=admin, its IMPOSSIBLE to start a new process as the current("correct") user without using ugly hacks like starting the app from the task scheduler(that service might be disabled) or injecting code into explorer.exe (ugly, hacky, and user might not have explorer.exe running, or it could even be running elevated even tho that is not recommended) The UAC plugin is somewhat hacky aswell, but it follows the wrapper model recommended by MS (well, they really want you to use MSI but that is not really relevant here)
See http://www.codeproject.com/KB/vista-...aElevator.aspx for task scheduler example, and http://www.codeproject.com/KB/vista-...nElevated.aspx for injection. There are some threads about this on the msdn/technet forums aswell.
RDaneel
18th January 2008 07:51 UTC
Yes, it may be a weird combination, but it was what I was used to doing since Win9x days... ;)
In any case, your suggestions for using HKCU for everything (uninstall info and Shell extension [un]registration) look like they will work, with one complication:
The component registration [for me] happens through the NSIS RegDLL statement, which names a DLL. This DLL has a DllRegisterServer entry point, which just calls the ATL UpdateRegistryFromResourceS function to interpret a "resource script" to actually make the all of the registry changes...
Since this chain of calls that starts with RegDLL doesn't have the ability to carry along parameters like "use HKCR or HKCU", life is more complicated (since you indicate that the HKCU "trick" doesn't work on systems earlier than Win2K).
Perhaps I would need to have the DllRegisterServer implementation itself decide at runtime which part of the registry to use based on something like "*can* I write to HKCR?" or not, and use the appropriate version of the "resource script". Hmmm.
Anders
18th January 2008 12:16 UTC
If you are willing to take over the RegDLL stuff and do it by hand, its even possible to register a dll hardcoded for HKCR into HKCU\Software\Classes without having source for dll (I have done this for my single user non admin hacked install of iTunes) I could dig up the code if you want (Might be in AutoIt or some weird language IIRC)
But since you control the dll, i'm sure there are better ways, either by using a special entrypoint for single installs (RegDll supports that), or have the installer write a "hint" in HKCU before it registers the dll, or as you say, check for write access to HKCR and fallback to HKCU
RDaneel
18th January 2008 19:17 UTC
Cool - I really should review the docs once in a while to notice that features like the optional entrypoint on RegDLL are there! ;)
This does look like the preferred way of making this work... since UnRegDLL does not seem to share this feature, I can presumably just always attempt an HKCU unregistration, and then fall back to a HKCR one if that errors out.
(Or, if detecting the error is not reliable enough, just do an explicit probe in the DLL's DllUnregisterServer to see if the HKCU registration entries are present.)
Joost Verburg
18th January 2008 21:06 UTC
Originally posted by Anders
When using RequestExectutionLevel=admin, its IMPOSSIBLE to start a new process as the current("correct") user without using ugly hacks like starting the app from the task scheduler(that service might be disabled) or injecting code into explorer.exe (ugly, hacky, and user might not have explorer.exe running, or it could even be running elevated even tho that is not recommended) The UAC plugin is somewhat hacky aswell, but it follows the wrapper model recommended by MS (well, they really want you to use MSI but that is not really relevant here)
Is such a hack currently possible with the UAC plug-in?
Joost Verburg
18th January 2008 21:15 UTC
Originally posted by RDaneel
Yes, it may be a weird combination, but it was what I was used to doing since Win9x days... ;)
On Win9x there is indeed not a lot of different between the the shell var contexts. If I remember correctly, a per-user desktop is available, but the Start Menu is always shared between all users. However, an installation in $PROGRAMFILES should normally be combined with "SetShellVarContext all". This will work fine with both Win9x and NT.
With Vista wrong setting will cause more troubles as compared to previous Windows versions.
Anders
18th January 2008 21:21 UTC
Originally posted by Joost Verburg
If I remember correctly, a per-user desktop is available, but the Start Menu is always shared between all users.
I don't think the start menu is shared (I know different user profiles can have seperate start menus (As for shared start menu, I can't remember if 9x has one or if it works))
The all user desktop does not work on 98 IIRC (even tho the folder is there, the content is not displayed on the desktop)
Originally posted by Joost Verburg
With Vista wrong setting will cause more troubles as compared to previous Windows versions.
These problems have been here since win2000 atleast, its just that most people run as admin on 2k/XP
Joost Verburg
18th January 2008 21:39 UTC
Originally posted by Anders
I don't think the start menu is shared (I know different user profiles can have seperate start menus (As for shared start menu, I can't remember if 9x has one or if it works))
The all user desktop does not work on 98 IIRC (even tho the folder is there, the content is not displayed on the desktop)
Then it's the other way around. I remember one of them doesn't work.
Originally posted by Anders
These problems have been here since win2000 atleast, its just that most people run as admin on 2k/XP
That's what I mean.