Win 7/UAC is driving me crazy.
From within my C++ application, I need to run an executable that requires elevation on Windows 7. I want to fire this thing off and wait for it to finish before proceeding. What's the easiest way to do this?
I normally do this kind of thing via CreateProcess()
, but it fails for executables that require elevation.
I tried running using cmd.exe /c ...
through CreateProcess
, which works but pops up an ugly cmd terminal window.
I am reading that ShellExecute()
will allow elevation, but it doesn't appear to be easy to wait for the exe to finish when using ShellExecute()
.
Will something simple like system()
work?
Any other ideas are greatly appreciated!
What you can do is create a pipe for the child process "stdin" (as if you were to redirect the input to that process) and wait for the pipe to break.
Note that the process will not really receive the redirected input.
E.g. if you try from unelevated command prompt to do
you will see elevation and the command window will wait until you close the separate window.
Use
ShellExecuteEx
, rather thanShellExecute
. This function will provide a handle for the created process, which you can use to callWaitForSingleObject
on that handle to block until that process terminates. Finally, just callCloseHandle
on the process handle to close it.Sample code (most of the error checking is omitted for clarity and brevity):
Specifying the "runas" verb for the
lpVerb
is what causes UAC to elevate the application that's about to be launched. This is the equivalent of setting the permissions level in the application's manifest to "requireAdministrator". It will require UAC elevation for both an administrator and a limited user.But it's worth noting that unless absolutely necessary, you should prefer the "standard" way of adding a manifest to the application you want to launch that specifies its required execution level. If you go this route, you will simply pass "open" as the
lpVerb
. A sample manifest is shown below:Finally, make sure that whatever element in your application triggers execution of the process requiring UAC elevation is marked accordingly. It's your job to model this in the user interface; Windows doesn't handle it for you. This is done by displaying the shield icon on the entry point; for example:
To run with elevated privileged, requires that the process launching this has elevated privileged. This usually require a secure service or something already running to launch your process. This is a change starting with Vista. It has to do with having the authority (via your ACL tokens) to be able to launch a process and launch it with the appropriate level of privileged inherited from the launching process. Microsoft has been pushing hard to have people create an elevated process that handles all elevated functionality needs and leave the rest in least privileged user space. Been doing this off and on since Vista was Alpha. It's a pain, but the way Microsoft would prefer you to do things for security reasons.
By the way, the ShellExec call will not work if you are launching your app from a secure location like Program Files directory, etc. Tried that before having to move to the service model years ago.
So to launch your process and by pass UAC, the only way to do it is to launch from a process that already has the security privileged to inherit