如何在没有提升的情况下执行应用程序?

发布于 2024-12-09 06:10:31 字数 305 浏览 0 评论 0原文

我想调用更新程序来检查更新(不是实际执行更新,而是仅检查是否有更新)。我想在后台默默地执行此操作。如果有更新,我会要求用户提升权限并使用该权限运行更新程序。检查涉及读取应用程序目录中的文件并将其中找到的版本与网站上的版本进行比较。

我怎样才能在没有提升的情况下运行它,仅用于检查? 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

人间☆小暴躁 2024-12-16 06:10:31

事实证明,我还有另一个错误,导致非提升的运行分支在所有情况下都运行。我在帖子中描述的模型有效。为了避免 Windows 推断需要提升权限,您需要添加清单资源。 (例如,如果你的应用程序exe的名称包含“updater”一词,它将被触发)

清单的内容如下:

<?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>

将其编译为.exe取决于你的编译器和环境,所以我只展示我的:Qt Creator 和 mingw-gcc:

为资源创建一个包含以下内容的 rc 文件:

1 24 DISCARDABLE manifest.xml

将此 rc 文件添加到您的 .pro 中,如下所示:

win32:RC_FILE = resources.rc

此后,不带动词参数的 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:

<?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.

残疾 2024-12-16 06:10:31

当您的应用程序出于某种原因请求时,会出现海拔提示。您可以使用应用程序清单来控制它。请参阅创建并嵌入应用程序清单 (UAC) 文章,详细了解如何添加清单。

我建议您执行以下操作:

  1. 将更新程序和更新检查程序分开,以便它们位于不同的 .EXE 文件中。
  2. UpdateChecker.exe 不需要管理员权限,因此清单的 requestedExecutionLevel 元素具有 asInvoker 级别。
  3. Updater.exe 需要管理员权限,因为它将更新的应用程序文件写入 Program Files。因此,其清单的 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:

  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.

恋你朝朝暮暮 2024-12-16 06:10:31

我建议使用以下场景之一:

  • 将该文件放在用户的配置文件中,而不是应用程序的路径中,
  • 将该文件的内容复制到用户的配置文件(如果它处于只读模式),然后运行 ​​QProcess::start()
  • 将该文件包含在 .qrc 文件中,然后将其提取到用户的配置文件中,以防读取或运行失败 QProcess::start()

I suggest to use one of these scenarios:

  • put that file in user's profile instead of application's path
  • copy content of that file to user's profile in case of it's in read only mode then run QProcess::start()
  • include that file inside .qrc file then extract it to user's profile in case of failing of read or run QProcess::start()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文