4

我的应用程序通过另一个名为“updater.exe”的应用程序有一个内置的自我更新系统,该应用程序与要更新的主应用程序位于同一文件夹中。它下载最新版本,终止旧版本(如果它正在运行),然后覆盖它。

问题是,要做到这一点,updater.exe 必须以管理员权限运行才能访问C:\Program Files\MyApp

到目前为止一切顺利,主应用程序以管理员权限(使用 UAC)运行 updater.exe,但随后出现问题:

更新完成后,我希望新安装的版本自动启动。你猜怎么着?当然,主应用程序也以管理员权限运行。场景很简单:

Main app[running as user] --> Updater App[run as admin] --> Main app[ADMIN again]

仅仅因为我的应用程序使用My.Settings对象,当它以管理员身份运行时它会丢失所有存储的设置,因为通常它总是以普通用户身份启动,并且您可能知道,My.Settings它是user-sensivite对象。

我该如何解决这样的问题?我四处搜索,但找不到与“以普通用户身份运行”相关的任何内容,但始终以管理员身份运行,这很容易。

好吧,老实说,另一方面,我认为这样的事情是不可能的,因为更新程序应用程序无法知道哪个特定用户启动了它。或者可以吗?我在这里缺少什么吗?

如果我是对的,那么不使用 My.Settings 而是使用 Windows 注册表来存储用户首选项是唯一的选择吗?

现在谢谢。

4

1 回答 1

3

“取消提升”子进程的一种方法是通过资源管理器启动它。这通常适用于普通 Win 用户。但是,如果 Explorer 本身正在提升运行,那么您尝试启动的应用程序也会如此。资源管理器可能正在提升运行,因为:

  • 活动用户是管理员(不仅仅是具有管理员权限的用户)
  • Explorer.exe是(重新)从一个命令窗口开始的......你明白了,正在运行提升

...可能还有其他人。

最好将此视为使用默认权限启动应用程序。如果运行提升的 Explorer 将启动提升的新实例,但原始的第一个Main App实例也将运行提升。

测试代码以使用复选框选择是否提升来启动相同的应用程序:

Dim proc = New Process
proc.StartInfo.UseShellExecute = True
proc.StartInfo.WindowStyle = ProcessWindowStyle.Normal
proc.StartInfo.WorkingDirectory = mypath

If chkAdmin.Checked Then                    ' run this app as admin
    proc.StartInfo.FileName = myApp
    proc.StartInfo.WorkingDirectory = mypath
    proc.StartInfo.Verb = "runas"           ' run "me" as admin
    proc.StartInfo.Arguments = ""
Else                                        ' run explorer w/app as arg
    ' de-elevate new app instance to run de-elevated
    proc.StartInfo.FileName = Path.Combine(windir, "explorer.exe")  
    proc.StartInfo.Verb = ""                ' important!
    proc.StartInfo.Arguments = myApp        ' send the child app name as arg
End If

proc.Start()

此图像显示了结果:

在此处输入图像描述

表单顶部的标签指示应用程序是否正在提升运行,每个应用程序实例都是由它之前的实例启动的。

向下的第二个窗口正在提升。当它启动下一个实例时,没有选中As Admin的复选框;因此,第三个实例是通过资源管理器启动的,并且没有运行提升。从 #5 开始的 #4 也是如此。

于 2015-06-10T01:39:30.110 回答