I've created a new ShellExecAsUser plugin:
It allows to execute the specified program in non-admin context, i.e. it is intended for installers that run with admin rights but need to execute something in non-admin context.
It uses desktop COM interface to execute process, so that process is launched by explorer (http://brandonlive.com/2008/04/27/ge...ou-part-2-how/).
Any comments are welcome.
ShellExecAsUser plugin
28 posts
Sound like something that can pretty useful 😎
Two questions:
* What operating systems does it work with? Any "fall back" mode for WinXP and Win2k?
* Can you please compile a Unicode version of that plug-in?
(Sorry, did not have time to examine your code yet)
Regards,
MuldeR.
Two questions:
* What operating systems does it work with? Any "fall back" mode for WinXP and Win2k?
* Can you please compile a Unicode version of that plug-in?
(Sorry, did not have time to examine your code yet)
Regards,
MuldeR.
* What operating systems does it work with? Any "fall back" mode for WinXP and Win2k?It should work starting from Win2k. On WinXP, Win2k (or if UAC is disabled) the plugin will do the launch using ShellExecute.
* Can you please compile a Unicode version of that plug-in?Ok I'll do.
Thank you!
I have adopted your ExecShellAsUser method into my StdUtils plug-in:
(ANSI and Unicode builds attached)
(ANSI and Unicode builds attached)
So, what, does this do what the UAC plugin was also designed to do, but without two installer instances?
Yup. It generates a non-elevated process right from the elevated installer instance.Originally Posted by MSG View PostSo, what, does this do what the UAC plugin was also designed to do, but without two installer instances?
Seems to work for me on Windows 7 (x64). I don't have any other UAC-enabled test platforms.
On Windows XP and earlier it simply falls back to the normal ShellExecute()...
I have adopted your ExecShellAsUser method into my StdUtils plug-in:Ok but note that I used another thread for desktop COM calls. Otherwise I (sometimes) got RPC_E_CANTCALLOUT_ININPUTSYNCCALL error, which is solved if you do it on another thread.
Thanks for the hint!Originally Posted by installer32 View PostOk but note that I used another thread for desktop COM calls. Otherwise I (sometimes) got RPC_E_CANTCALLOUT_ININPUTSYNCCALL error, which is solved if you do it on another thread.
(I already noticed that CoInitializeEx() fails, because, I think, COM already is initialized with other parameters for the calling thread. So I switched back to CoInitialize() again. But I will implement your suggestion now)
[UPDATE] Done. New version is attached. [/UPDATE]
Very cool! I use the UAC plugin for double install mode all-through, for which case I guess it is more convenient to have two instances. But this is a very cool alternative, and a lot simpler to use!
Sorry, here are some more fixes:
This COM hack is problematic and/or broken when:
A)
Explorer is not running
B)
Explorer is elevated (Rare, but some people do it)
C)
Desktop user is not the correct parent:
User A is logged on,
runs setup as non-admin user B with runas.exe,
setup is elevated with user C;
The correct user is B, not A.
A)
Explorer is not running
B)
Explorer is elevated (Rare, but some people do it)
C)
Desktop user is not the correct parent:
User A is logged on,
runs setup as non-admin user B with runas.exe,
setup is elevated with user C;
The correct user is B, not A.
In case (A) it will fall back to the normal ShellExecute(). Not ideal, but well...
I'm not sure what will happen in case (B) or how to reproduce this, but I guess in that case we will either fail to get the COM interface and thus fall back to the normal ShellExecute(), or we will simply create an elevated instance.
Again not ideal, but if you run your Explorer in an elevated way, then problems are preprogrammed anyway 🙄
(And in case (C) it may depend on the situation/purpose whether user A or B is the "correct" one)
I'm not sure what will happen in case (B) or how to reproduce this, but I guess in that case we will either fail to get the COM interface and thus fall back to the normal ShellExecute(), or we will simply create an elevated instance.
Again not ideal, but if you run your Explorer in an elevated way, then problems are preprogrammed anyway 🙄
(And in case (C) it may depend on the situation/purpose whether user A or B is the "correct" one)
Anders
You are right and I'll add your remarks to plugin description, though I think it's quite uncommon and as such these limitations are acceptable to many people.
You are right and I'll add your remarks to plugin description, though I think it's quite uncommon and as such these limitations are acceptable to many people.
I have updated my StdUtils plug-in to use the "new" plug-in API, i.e. get rid of explicit unload.
Furthermore I added a version of ExecShell with wait capability as well as some more convenience functions.
New version here:
(BTW: Could some mod please delete the obsolete versions attached to my previous posts?)
Furthermore I added a version of ExecShell with wait capability as well as some more convenience functions.
New version here:
(BTW: Could some mod please delete the obsolete versions attached to my previous posts?)
In case somebody is interested, I just uploaded a new version of my StdUtils plug-in:
I've just uploaded yet another update, which fixes a potential crash related to CoUninitialize() and certain certain Shell Extensions. In my case it was Tortoise GIT. Put simply, CoUninitialize() might still crash, even if all COM interfaces were released properly before. Happens if there are outstanding messages. It turns out we must dispatch all pending messages explicitly before calling CoUninitialize().Originally Posted by LoRd_MuldeR View PostIn case somebody is interested, I just uploaded a new version of my StdUtils plug-in:
http://nsis.sourceforge.net/StdUtils_plug-in
As this might be relevant for all NSIS plug-in's that deal with COM interfaces (and the Shell), you might want to have a look here:
(As requested in the NSIS WIKI, I'm using this topic for feedback on StdUtils.)
LoRd_MuldeR, any plans to add a x86/x64 check to StdUtils? I am currently using...
LoRd_MuldeR, any plans to add a x86/x64 check to StdUtils? I am currently using...
...but maybe there is a cleaner way to do this?System::Call "kernel32::GetCurrentProcess() i .s"
System::Call "kernel32::IsWow64Process(i s, *i .r0)"
NSIS has that built-in already 🙂
!include "LogicLib.nsh"
!include "x64.nsh"
${If} ${RunningX64}
MessageBox MB_OK "We are running on x64!"
${EndIf}
LOL Nice, thanks. Back in the day that didn't exist... 🙂
The system::call code is still the same behind the scenes 😉Originally Posted by Theresias View PostLOL Nice, thanks. Back in the day that didn't exist... 🙂
ShellExecAsUser not work in nsis unicode
hi
i use from ShellExecAsUser plugin for open the exe files run as user
Plugin:
when i use the nsis ansi then ShellExecAsUser plugin works correctly and exe file opened.
but if use from the nsis unicode:
plugin unable to open file and show message:

hi
i use from ShellExecAsUser plugin for open the exe files run as user
Plugin:
when i use the nsis ansi then ShellExecAsUser plugin works correctly and exe file opened.
Section ShellExecAsUser::ShellExecAsUser "open" "C:\1.exe" SectionEnd
[B]Unicode true [/B] Section ShellExecAsUser::ShellExecAsUser "open" "C:\1.exe" SectionEnd
plugin unable to open file and show message:
There is no Unicode version of that plug-in. Try contacting the author.
Edit: A Unicode version has now been added to the wiki by the author.
Edit: A Unicode version has now been added to the wiki by the author.
Hi
Does anybody know a method that I can force the main NSIS Process to wait for the ShellExecAsUser process to end before it is possible to do anything else?
Regards
Bernd
Does anybody know a method that I can force the main NSIS Process to wait for the ShellExecAsUser process to end before it is possible to do anything else?
Regards
Bernd
No I don't believe that is possible. The COM interface used to ShellExecute does not support waiting. You need ShellExecuteEx to wait, and even then, it would not work because the wait handle is in the wrong process.Originally Posted by BerndS View PostDoes anybody know a method that I can force the main NSIS Process to wait for the ShellExecAsUser process to end before it is possible to do anything else?
Why do you need to wait for a "as user" process?
Hi
It is not essential to wait for the user process but it would feel better ;-)
I start a user process that does some downloads and configuration stuff when the main part of the installer is done. As I can click the "next" buttons in the NSIS part I can end the installer but the "user" part is not finished and is working ... this just does not look very nice.
Regards
Bernd
It is not essential to wait for the user process but it would feel better ;-)
I start a user process that does some downloads and configuration stuff when the main part of the installer is done. As I can click the "next" buttons in the NSIS part I can end the installer but the "user" part is not finished and is working ... this just does not look very nice.
Regards
Bernd
Assuming this is a "RequestExecutionLevel Admin + HKLM + $ProgramFiles" installer. These are multi-user installers and any per-user initialization should happen the first time a user runs the applications from the start menu. In a extreme case; someone could use fast user switching and start the application as a 3rd user (not the administrator and not the "user") before your call to ShellExecAsUser has completed.Originally Posted by BerndS View Post
I start a user process that does some downloads and configuration stuff when the main part of the installer is done.