Skip to content
⌘ NSIS Forum Archive

Shortcuts on Vista

119 posts

alex5#

Shortcuts on Vista

What is the proper way to create shortcuts on Windows Vista ?
If I set 'RequestExecutionLevel admin', install is running as administrator and shortcuts are created for administrator not the currently logged in user.
If RequestExecutionLevel is set to user, then shortcuts are properly created, but you can't write to Program Files, write unistall registry key...

How can I create shortcuts for current user (SetShellVarContext is set to current) ?

Thanks

Alex

**********************************************************
[edit] 08/05/07 - DrO
Please refer to http://nsis.sourceforge.net/UAC_plug-in for information and plugin regarding this thread
Takhir#
I could reproduce this with "Standart User" account 🙁 UAC not only elevates execution level, but changes user as well... Even desktop links created for UAC requested admin account.
stb#
I think this is a serious problem which should be handled by NSIS. Of course we could build wrapped installers where some are running as user and some as admin. But this will be some very basic problem with Vista in general.

Problems:
1. Registry: HKCU
2. User profile directory (shortcuts and more)
3. "Run ... now" on finish page (this is a small issue in XP too if the installer is run as admin there). This might be a problem for other (custom) ShellExec's, too.

Can NSIS change its execution level at runtime? Does anybody know what Vista does here?

I think the best solution would be to run as admin in general when RequestExecutionLevel admin is set but to make special handling for HKCU / shortcuts.

Could NSIS detect what user was active before elevating?
Anders#
I'm developing a plugin that hopefully will help to deal with these Vista problems, its still "in Beta" so don't blame me if it doesnt work or blows up in your face (or all over your HD)

Checkout UAC_RealWorldExample (Known issue: Does not print to instfiles page log or any kind of success feedback when elevated)


http://stashbox.org/13537/UAC%20v0.0.5b.zip

IMHO The shortcut problem is not really a problem, when using RequestExecutionLevel admin it is a "All users" install, if you want to use RequestExecutionLevel user, you should write the uninstall entry in HKCU and install your files in $LOCALAPPDATA
stb#
I agree: short cut is no real problem, I think I will just disable the possibility to install them for "current user". I know of current user installs but this is not an option for most of my installers here.

I use HKCU to store some settings for the user who installs the application. E.g. the license text can be stored as "seen" for the use who read it during install. Other users will get it on first application start. And I store language settings and more for the installing user.

Thanks for the new plugin, is there some short documentation how the functions work (other than the examples)?

As far as I can see this works like:

- start in user mode
- elevate to admin mode (with error/retry handling)

Can I un-elevate (back to user mode)?
If yes, I guess re-elevating (elevating for the 2nd time) would require additional password entry.

It seems the current process is changed at run-time. What does change on elevation? Username? access rights? "current user" profile (NSIS vars?)

What about my Exec problem? Currently I would like to run the installer as admin (could be done by requestlevel user and elevating in .oninit) but make the run caused by the finish page checkbox ("run now ...") to run the app as original user.
kichik#
The SAFER plug-in should solve the Exec problem. But if the user is switched and not elevated, you won't get the original user.
Anders#
There are no docs at this time, the exported functions have a little bit of text if you look in uac.cpp

You cant un-elevate once you have elevated (Well you could call UAC::Exec on yourself but that would be the same as a "current user" install)


This plugin should solve the Exec problem, use Process Explorer (Sysinternals/MS), turn on the User and Intergrity level columns and run the realworld example as a normal user elevating with a different admin account


What changes after elevation depends on whether UAC is on or off.

UAC on and the user is an admin (Split token):
Nothing really changes
UAC::IsAdmin returns 1 after elevation and 0 before
UAC::SupportsUAC returns 1
UAC::GetElevationType returns 3 before successfull elevation with RunElevated and 2 after

UAC off and the user is an admin:
Nothing really changes
UAC::IsAdmin returns 1
UAC::SupportsUAC returns 0
UAC::GetElevationType returns 1

User not member of admin group:
Everything changes (Username/Profile/HKCU part of registry)
UAC::IsAdmin returns 0 before elevation and 1 after
UAC::SupportsUAC return depends on whether UAC is on/off
UAC::GetElevationType again depends on UAC on/off
(NOTE: Vista seems totally broken in this configuration (IF UAC IS OFF), try right clicking on a .exe and choose "Run as administrator", nothing happens, in this case the plugin uses its own custom RunAs dialog)


on pre vista systems UAC::GetElevationType always returns 0

the UAC plugin can allow you to run in "current user" mode, if $0 == 1223 after UAC::RunElevated the user clicked cancel in the UAC/RunAs dialog (This is all up to the creator of the installer)

The SAFER plugin doesnt work very well on Vista, MS broke the SAFER api on this OS (It still works but the process will still run @ High integrity level)

Note: This is all from memory, i might have missed something
stb#
Thanks a lot, Anders.

Some questions:
Can you explain Exec a bit more? How does this work? Does this run the process with the original user (calling the installer)? How does UAC::Exec behave on Non-UAC-systems?

Does this help with RunAs (WinXP) or is RunAs with XP always independent from the original user (I guess this is the case, so maybe the "run now" on the finish page is bad for XP when RunAs (possibly) is used).

I'm trying to understand this (before testing/verifying).

You wrote: "in this case the plugin uses its own custom RunAs dialog"
What do you mean with this? How is the "run as dialog" correlated to NSIS here?
Anders#edited
Run process explorer, you can see two instances(processes) of your setup, one running as the user that started the setup and one running at high integrity level (and possibly as another user if the original user was not a member of the admin group) When you use UAC::Exec/ExecWait/ShellExec/ShellExecWait the 2nd elevated process will send a message to the original process telling it to start a process (uses WM_COPYDATA)

Running as admin on pre vista or admin with UAC off on vista will only use one process and UAC::Exec just calls CreateProcess without any trickery

EDIT: on win2000/xp it somewhat emulates the vista elevation, UAC::Exec will start a process as the original user
I guess you could use the SAFER plugin on xp so the process spawned at the finish page does not run as admin even if the real user is admin


UAC::RunElevated just does ShellExecute on itself using the runas verb (The documented way to get the uac dialog on vista) this also works on Win2k/XP except you get the old school runas ofcourse. If a non-admin user on vista with UAC off is detected, using runas with ShellExecute will not work at all so UAC::RunElevated uses its own dialog that emulates the pre vista runas instead
Anders#
New version: http://stashbox.org/13698/UAC%20v0.0.5c.zip

IsAdmin can now handle a restricted token on <NT6, no other changes
Anders#
New version: http://stashbox.org/15549/UAC%20v0.0.5d.zip

Fixed a bug in IsAdmin, please update
stb#
@Anders: You call UAC::Unload in .oninstfailed/.oninstsuccess.
Is this necessary?

I use Quit in many places in my scripts (to abort the installer immediately) and this will not run those callbacks, so UAC::Unload will not run. Is it safe to Quit without "UAC::Unload"?
Anders#
It will not crash if you dont call unload, but it will probably leave uac.dll in $pluginsdir so you will leave stuff behind in the users $temp dir. The only thing UAC::Unload does is to call FreeLibrary on itself so you should probably call it if possible. If you call Quit before you call any UAC function you dont need to unload (IsAdmin,SupportsUAC and GetElevationType is safe to use without unload, RunElevated and ExecCodeSegment is not)
stb#
I could not try it myself (yet), what about error level return values? I use "set error level" within my script and the outer process should return those error level value, too (if set).
stb#
Ah, found it:

RunElevate returns
"r2 is the ExitCode of the elevated fork process (The NSIS errlvl is also set to the ExitCode)"
stb#
The plugin seems to work. Thanks, Anders!

UAC::GetElevationType and UAC::SupportsUAC return "0" for XP. But RunElevated supports RunAs dialog (nice feature). It would be nice to have functions UAC::GetRunAsType and UAC::SupportsRunAs so one can show some message to the user before the RunAs dialog is shown. Seems that at least SupportsRunAs is already implemented (but not exported to NSIS).
Anders#
UAC::GetElevationType and UAC::SupportsUAC return 0 on XP and below because those are Vista specific.

I think RunAs is supported on all NT systems (And it is not needed on 9x) atleast it works on w2k and up. I don't have a NT4 box to test on so im not sure. What would UAC::GetRunAsType do, tell you what kind of runas dialog you would get (Does it really matter)?

I like the idea of the messagebox before elevation (Even tho users will get used to the elevation on Vista), I could probably create something like UAC::SupportsRunAs
stb#
GetRunAsType could return "1" if this is the inner process. I currently check myself for "/UAC:" in CMDLINE. I have to do this because the MessageBox I show will appear twice if I show it always before RunElevated.

I don't really know whether GetElevationType will really return the state of "inner" or "outer" process (imagine outer user IS admin, even with UAC -- could be caused by automatic install scripts). So maybe GetRunAsType could be something like "IsInnerProcess"...

I simulate SupportsRunAs for now by checking the OS major version against "5". AFAIK NT4 does not have something like RunAs (at least "runas.exe" is only available with 2k/XP).
Anders#
You dont really need to know if you are the inner process or not, if IsAdmin returns 1 you are either already admin or the elevation has been performed
stb#
@Anders: I need to know. It is helpful anyway to know this, but if I don't detect this (inner process yes/no), I will show the warning message twice if the user logs in as non-admin in RunAs dialog (try for yourself; it took me some minutes to detect what was going on there).
FrozenFire#
Downloaded your pluggin today to try to fix some exec problems i've been having in vista. I ended up making an function to install files in restricted areas and calling it to run in ellivated mode, but it didn't work, instead producing an error when the installer tried to write to the secured area.
stb#
Post code here for help.

UAC plugin works fine for me. One important thing to know is that the whole installer will run elevated (or not), so you cannot have a single function run elevated and the rest unelevated (you would have to do this manually).
MarcOfChaos#
Hello,

I am trying to make an installer which runs with "RequestExecutionLevel user".

During the installation process the user can select whether he just wants to execute or install the software. If he wants to install the software I use UAC::RunElevated to restart the installer with all necessary tokens. This works fine if the current user is an admin.
When I try it with an ordinary user the RunAs Dialog is dispalyed but the second program is not executed.

RunElevated returns a value of 6 which is (to my knowledge) the error code for a missing handle.

Any ideas what is happening there?
MarcOfChaos#
Hello Anders,

Thank you for your reply.
Unfortunately a code snippet will not be of much help.
I only call UAC::RunElevated when logged in as a domain user in Win Vista.

But the thing gets even stranger: I tested the installer from my desktop. When I copy the same installer to some other folder (e.g. \programms) UAC::RunElevated runs perfectly (RunAs Dialog is being displayed and the installer is restarted with the correct privileges). Btw: It also does not work when I run it under \users.
Maybe it is some kind of special virtualization with Vista.
Any ideas what is causing this?