Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute an app without elevation?

I want to invoke an updater to check for updates (not to actually do the update but only check if there is any). I would like to do this in the background and silently. If there is an update, I would ask the user for elevated permissions and run the updater with that. The checking involves reading a file in the application's directory and comparing the version found in it with the one on a website.

How can I run it without elevation for checking only? QProcess::start() fails because it needs elevated permission and ShellExecute only works if I add the "runas" verb for the same reason (which I only want if there would be actually writing in that directory i.e. I want to perform an update). I'm guessing I need to add some sort of manifest but I don't know its contents.

like image 969
Tamás Szelei Avatar asked Oct 12 '11 18:10

Tamás Szelei


2 Answers

So it turns out that I had another bug that caused the non-elevated running branch to run in all cases. The model I described in the post works. To avoid Windows infering the need for elevated permissions, you need to add a manifest resource. (for example, if the name of your application exe contains the word "updater" it will be triggered)

The contents of the manifest are the following:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
            </requestedPrivileges>
        </security>
    </trustInfo>
</assembly>

Compiling it to your .exe depends on your compiler and environment, so I'm only showing mine: Qt Creator and mingw-gcc:

Create an rc file for the resources with the following content:

1 24 DISCARDABLE manifest.xml

Add this rc file to your .pro like this:

win32:RC_FILE = resources.rc

After this, ShellExecute without the verb paramter will run without elevation, and using "runas" will run it with elevation.

like image 177
Tamás Szelei Avatar answered Sep 23 '22 02:09

Tamás Szelei


Elevation prompt appears when your application requests it, for some reason. You can control it with the application manifest. See Create and Embed an Application Manifest (UAC) article for details on how to add the manifest.

I would suggest you the following:

  1. Separate your Updater and Update Checker, so that they're in different .EXE files.
  2. UpdateChecker.exe requires no administrator privileges, and thus requestedExecutionLevel element of the manifest has asInvoker level.
  3. Updater.exe requires administrator privileges because it writes updated application file into Program Files. Therefore requestedExecutionLevel element of its manifest has requireAdministrator level.

In your program you can launch UpdateChecker.exe whatever way you like. To start Updater.exe you will have to use ShellExecute; if the application has the manifest (and I strongly recommend embedding manifest) it will show UAC prompt for elevation if the application wants administrator privileges. There's no need to use runas verb.

Alternatively you can check whether update is available or not from your main application. And launch the Updater.exe only when there's a new version on the server.


Another option would be to make Updater.exe both check for update and apply it if there's one, just like you do it now. In this case Updater.exe should have asInvoker level in its manifest. When it starts, without parameters, it checks whether there's a new version on the server. If it finds newer version, it re-launches itself with administrator privileges and passes a command-line parameter, for example /doUpdate, which instructs it do perform the actual update.

In order to re-launch itself elevated, it has to use ShellExecute function and runas verb, because ShellExecute will be unable to detect automatically your Updater.exe now requires administrative privileges.

Keep in mind that the meaning of runas verb differs between Windows XP and Windows Vista/7, so you should handle this situation if you want to support previous versions of Windows. The first approach I described will work on Windows XP without additional handling.

like image 42
Alexey Ivanov Avatar answered Sep 21 '22 02:09

Alexey Ivanov