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

时间:2011-10-12 18:00:08

标签: qt uac shellexecute

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

如何在没有高程的情况下运行它仅用于检查? QProcess::start()失败,因为它需要提升权限,ShellExecute只有在我添加“runas”动词时才会出现相同的原因(我只想在那个目录中实际写入,即我想要执行)更新)。我猜我需要添加某种清单,但我不知道它的内容。

3 个答案:

答案 0 :(得分:10)

所以事实证明我有另一个错误导致非升级的运行分支在所有情况下运行。我在帖子中描述的模型有效。要避免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”将以高程运行它。

答案 1 :(得分:4)

由于某种原因,当您的应用程序请求时会出现提升提示。您可以使用应用程序清单来控制它。有关如何添加清单的详细信息,请参阅Create and Embed an Application Manifest (UAC)文章。

我建议你:

  1. 更新程序更新检查程序分开,以便它们位于不同的.EXE文件中。
  2. UpdateChecker.exe不需要管理员权限,因此清单的requestedExecutionLevel元素具有asInvoker级别。
  3. Updater.exe需要管理员权限,因为它会将更新的应用程序文件写入Program Files。因此,其清单的requestedExecutionLevel元素具有requireAdministrator级别。
  4. 在您的程序中,您可以按照自己喜欢的方式启动UpdateChecker.exe。要启动Updater.exe,您必须使用ShellExecute;如果应用程序具有清单(我强烈建议嵌入清单),如果应用程序需要管理员权限,它将显示UAC提示提升。没有必要使用runas动词。

    或者,您可以从主应用程序检查更新是否可用。只有在服务器上有新版本时才启动Updater.exe。


    另一个选择是使Updater.exe检查更新并在有一个时应用它,就像你现在这样做。在这种情况下,Updater.exe的清单中应该有asInvoker级别。当它启动不带参数时,它会检查服务器上是否有新版本。如果找到更新版本,则以管理员权限重新启动并传递命令行参数,例如/doUpdate,指示它执行实际更新。

    为了重新启动自身,它必须使用ShellExecute函数和runas动词,因为ShellExecute将无法自动检测到您的Updater.exe现在需要管理权限

    请记住runas动词的含义在Windows XP和Windows Vista / 7之间有所不同,因此如果要支持以前版本的Windows,则应该处理这种情况。我描述的第一种方法适用于Windows XP,无需额外处理。

答案 2 :(得分:0)

我建议使用以下方案之一:

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