Old 23rd November 2015, 19:50   #1
dolu
Junior Member
 
Join Date: Nov 2015
Posts: 1
ExecWait and run uninstall elevated

Hi all,
I'm trying to get an installer which uninstall previous version if needed.
So, everything is ok when the windows user is admin
But for a classical user, install part works well, but ExecWait never returns.

code:
...
!include "UAC.nsh"
...
RequestExecutionLevel admin
...
Function .onInit
!insertmacro UAC_RunElevated
...
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "$msgAlreadyInstalled" IDOK uninst
Abort
;Run the uninstaller
uninst:
ClearErrors
ExecWait '$R0 _?=$INSTDIR'
IfErrors no_remove_uninstaller done
no_remove_uninstaller:
...
done:
FunctionEnd
...



What's wrong ?
Is there another way to call the uninstaller inside the installer ?
Thanks.
dolu is offline   Reply With Quote
Old 23rd November 2015, 21:55   #2
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
If you try to start a process that requires "elevation" (i.e. admin-rights), which your Uninstaller probably does, from a "non-elevated" process (i.e. a process not running with admin rights) using a function like Exec or ExecWait, then it's just going to fail! You can use ExecShell, which will trigger an UAC dialog and, if the user agrees, launch the process. But then you can not wait for the process to finish...

I implemented the ExecShellWaitEx function for exactly that reason:
http://muldersoft.com/docs/stdutils_....html#a3d3af46

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 24th November 2015, 08:08   #3
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,262
The UAC plug-in is difficult to use correctly so please consider a different approach.

Your code is fundamentally broken, you cannot combine RequestExecutionLevel admin and the UAC plug-in!

You are not quoting the path in ExecWait and it probably should be silent.

Normally I'd ask you to report your Windows, NSIS and UAC plug-in versions but your insufficient and broken example code is not worth my time trying to reproduce your problem...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 24th November 2015, 08:14   #4
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,262
Quote:
Originally Posted by LoRd_MuldeR View Post
You can use ExecShell, which will trigger an UAC dialog and, if the user agrees, launch the process. But then you can not wait for the process to finish...

I implemented the ExecShellWaitEx function for exactly that reason:
http://muldersoft.com/docs/stdutils_....html#a3d3af46
ExecShell nor any kind of ExecShellWait is enough to reliably start a process elevated, this is bad advice.

Two issues off the top of my head:

A) Vista, 7 (and 8?) with UAC turned off.

B) 2000, XP and 2003 with non-admin credentials used in the runas dialog.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 24th November 2015, 08:50   #5
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Anders View Post
ExecShell nor any kind of ExecShellWait is enough to reliably start a process elevated, this is bad advice.
Sure, ShellExecute(Ex) cannot "reliably" start an elevated process from a non-elevated one, because the user has to explicitly agree in the UAC dialog to launch the process. If the user doesn't agree (or the timeout hits), the process won't start. And, if the current user in not "admin", he even has to enter "admin" credentials into the UAC dialog in order to launch the process.

But: Using ShellExecute(Ex) it's at least possible to start a process that requires "elevation" from a non-elevated process (and if user declined, you can detect the issue and just retry) - whereas Exec or ExecWait just fail in that situation with error #740.

See also:
http://blogs.msdn.com/b/winsdk/archi...plication.aspx


Quote:
Originally Posted by Anders View Post
A) Vista, 7 (and 8?) with UAC turned off.
I think if UAC is turned off, then ShellExecute(Ex) just launches the "elevated" process without showing the UAC dialog. In this special situation Exec or ExecWait could do the job too, but they'd start failing as soon as UAC is actually not turned off on some computer. ShellExecute(Ex), on the other hand, works fine under both conditions, I believe.

Quote:
Originally Posted by Anders View Post
2000, XP and 2003 with non-admin credentials used in the runas dialog.
Since these "legacy" systems didn't have UAC, they just ignore the "elevation" request from the Manifest.

If a "non-admin" user launches your installer on any of these systems (or an "admin" user uses run as to run your installer under a "non-admin" account), you have a problem anyway! The installer needs to detect this via UserInfo plug-in and abort...

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 24th November 2015, 09:41   #6
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,262
Quote:
Originally Posted by LoRd_MuldeR View Post

I think if UAC is turned off, then ShellExecute(Ex) just launches the "elevated" process without showing the UAC dialog. In this special situation Exec or ExecWait could do the job too, but they'd start failing as soon as UAC is actually not turned off on some computer. ShellExecute(Ex), on the other hand, works fine under both conditions, I believe.
Why do you think I called it an issue? When you turn UAC off on these systems, ShellExecute with the runas verb just starts the process unelevated! The UAC plug-in detects this and displays its own RunAs dialog to handle this case. In other words, when you turn off UAC then NT6 acts like NT5 except that the runas verb is broken...

Quote:
Originally Posted by LoRd_MuldeR View Post
Since these "legacy" systems didn't have UAC, they just ignore the "elevation" request from the Manifest.

If a "non-admin" user launches your installer on any of these systems (or an "admin" user uses run as to run your installer under a "non-admin" account), you have a problem anyway! The installer needs to detect this via UserInfo plug-in and abort...
Sure but that is not what we are talking about here. You implied that ExecShell[Wait] is a simple drop in solution to start something elevated and it is not. What we need is a plug-in that does this properly but that is not really relevant if the OP wants to continue using the UAC plug-in...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 24th November 2015, 09:50   #7
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Quote:
Originally Posted by Anders View Post
Why do you think I called it an issue? When you turn UAC off on these systems, ShellExecute with the runas verb just starts the process unelevated! The UAC plug-in detects this and displays its own RunAs dialog to handle this case.
I was never suggesting to use the "runas" verb. If the "nested" (Un)Intstaller you try to launch requires elevation, as per its Manifest, ShellExecute(Ex) takes care of "elevation" automatically. It will trigger an UAC dialog, when the (Un)Intstaller gets launched from a non-elevated process. At the same time Exec and ExecWait would just fail (error #740), if you try to launch an (Un)Installer that requires elevation, as per its Manifest, from a non-elevated process. In the (rare) case that UAC is turned off, using Exec and ExecWait would work too. But otherwise they'd fail in that situation. At the same time, using an ShellExecute(Ex) solution should work in all cases.

Quote:
Originally Posted by Anders View Post
Sure but that is not what we are talking about here. You implied that ExecShell[Wait] is a simple drop in solution to start something elevated and it is not. What we need is a plug-in that does this properly...
I did not say that it (necessarily) does "start something elevated". What I actually said is that it allows for launching a process that requires elevation (as per its Manifest) from a non-elevated process. In that case Exec and ExecWait would just fail.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 24th November 2015, 10:07   #8
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,262
Quote:
Originally Posted by LoRd_MuldeR View Post
I was never suggesting to use the "runas" verb. If the "nested" (Un)Intstaller you try to launch requires elevation, as per its Manifest, ShellExecute(Ex) takes care of "elevation" automatically, i.e. it will trigger an UAC dialog, when the (Un)Intstaller gets launched from a non-elevated process. At the same time Exec and ExecWait would just fail (error #740), if you try to launch an (Un)Installer that requires elevation, as per its Manifest, from a non-elevated process. In the (rare) case that UAC is turned off, using Exec and ExecWait would work too. But otherwise they'd fail in that situation. At the same time, using an ShellExecute(Ex) solution should work in all cases.


I did not say that it does "start something elevated". What I actually said is that it allows for launching a process that requires elevation (as per its Manifest) from a non-elevated process. In that case Exec and ExecWait would just fail.
You did see that the code in the initial post already asks to be elevated right? If you are suggesting the he/she should use ShellExecute without the run as verb then that is even more crazy.

ShellExecuteEx works in all cases depending on your definition of working. It works differently depending on the system configuration which obviously is not a good thing. The OP wants to start a new process with administrator rights and a simple ShellExecuteEx is not enough because there are several corner cases you need to handle. Only a plugin with a specific RunAsAdmin type function can accomplish this in a satisfactory fashion.

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 24th November 2015, 18:18   #9
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
If I understood the OP right, he wants to launch an uninstaller from his "main" installer - which works from elevated ("admin") user context, but not from non-elevated ("classical") user context. So, it sounds to me like the typical "unable to start a process that requires elevation from non-elevated process" (code #740) problem. The uinstaller probably requires elevation, as per its Manifest, so Exec or ExecWait are going to fail when the "main" installer is not already elevated. The ExecShellWaitEx function can resolve that problem.

If we are running on a "legacy" system without UAC, there is no such thing as "elevation". So there are only two possibilities: Either the current (logged on) user is an "admin" user, or not. Consequently, the only thing that really can be done by an (un)installer that requires "admin" rights is: Detect the current user-type via UserInfo plug-in – and abort with error if the current user is not an "admin" user.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 24th November 2015, 19:34   #10
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,262
Angry

Quote:
Originally Posted by LoRd_MuldeR View Post
So, it sounds to me like the typical "unable to start a process that requires elevation from non-elevated process" (code #740) problem. The uinstaller probably requires elevation, as per its Manifest, so Exec or ExecWait are going to fail when the "main" installer is not already elevated. The ExecShellWaitEx function can resolve that problem.
Why do you insist on going round in circles? We already know the installer requested elevation in the manifest so it is certainly not the typical case you are referring to. If UAC is in the default configuration then we would already be elevated and if not then CreateProcess is not going to return 740. I have already told you several reasons why ShellExecuteEx alone is not enough so please stop recommending it!

Quote:
Originally Posted by LoRd_MuldeR View Post
If we are running on a "legacy" system without UAC, there is no such thing as "elevation". So there are only two possibilities: Either the current (logged on) user is an "admin" user, or not. Consequently, the only thing that really can be done by an (un)installer that requires "admin" rights is: Detect the current user-type via UserInfo plug-in – and abort with error if the current user is not an "admin" user.
It might not have been called elevation back then but it is possible to elevate from normal user to admin on 2000/XP/2003 and the UAC plug-in does it. Your two possibilities suddenly became three. In UAC parlance this is called over the shoulder elevation...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Tags
auto, elevated, execwait, uninstall

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump