如何在没有提升的情况下执行应用程序?
我想调用更新程序来检查更新(不是实际执行更新,而是仅检查是否有更新)。我想在后台默默地执行此操作。如果有更新,我会要求用户提升权限并使用该权限运行更新程序。检查涉及读取应用程序目录中的文件并将其中找到的版本与网站上的版本进行比较。
我怎样才能在没有提升的情况下运行它,仅用于检查? QProcess::start()
失败,因为它需要提升的权限,并且 ShellExecute
仅当我出于相同原因添加“runas”动词时才有效(我只希望如果有实际上是在该目录中写入,即我想执行更新)。我猜我需要添加某种清单,但我不知道它的内容。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
事实证明,我还有另一个错误,导致非提升的运行分支在所有情况下都运行。我在帖子中描述的模型有效。为了避免 Windows 推断需要提升权限,您需要添加清单资源。 (例如,如果你的应用程序exe的名称包含“updater”一词,它将被触发)
清单的内容如下:
将其编译为.exe取决于你的编译器和环境,所以我只展示我的:Qt Creator 和 mingw-gcc:
为资源创建一个包含以下内容的 rc 文件:
将此 rc 文件添加到您的 .pro 中,如下所示:
此后,不带动词参数的 ShellExecute 将在没有提升的情况下运行,并使用“runas”将以海拔高度运行它。
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:
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:
Add this rc file to your .pro like this:
After this, ShellExecute without the verb paramter will run without elevation, and using "runas" will run it with elevation.
当您的应用程序出于某种原因请求时,会出现海拔提示。您可以使用应用程序清单来控制它。请参阅创建并嵌入应用程序清单 (UAC) 文章,详细了解如何添加清单。
我建议您执行以下操作:
requestedExecutionLevel
元素具有asInvoker
级别。requestedExecutionLevel
元素具有requireAdministrator
级别。在您的程序中,您可以按照您喜欢的方式启动 UpdateChecker.exe。要启动 Updater.exe,您必须使用 ShellExecute;如果应用程序有清单(我强烈建议嵌入清单),如果应用程序需要管理员权限,它将显示 UAC 提升提示。无需使用
runas
动词。或者,您可以从主应用程序检查更新是否可用。仅当服务器上有新版本时才启动 Updater.exe。
另一种选择是让 Updater.exe 检查更新并应用它(如果有),就像您现在所做的那样。在这种情况下,Updater.exe 在其清单中应具有
asInvoker
级别。当它启动时,不带参数,它会检查服务器上是否有新版本。如果它找到更新的版本,它会使用管理员权限重新启动自身,并传递一个命令行参数,例如/doUpdate
,指示它执行实际的更新。为了重新启动提升的自身,它必须使用
ShellExecute
函数和runas
动词,因为ShellExecute
将无法自动检测您的更新程序.exe 现在需要管理权限。请记住,
runas
动词的含义在 Windows XP 和 Windows Vista/7 之间有所不同,因此如果您想支持以前版本的 Windows,则应该处理这种情况。我描述的第一种方法适用于 Windows XP,无需额外处理。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 hasasInvoker
level.requestedExecutionLevel
element of its manifest hasrequireAdministrator
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 userunas
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 andrunas
verb, becauseShellExecute
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.我建议使用以下场景之一:
QProcess::start()
QProcess::start()
I suggest to use one of these scenarios:
QProcess::start()
QProcess::start()