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.
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.
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:
requestedExecutionLevel
element of the manifest has asInvoker
level.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With