【问题标题】:Run child process non-elevated from an elevated/As Admin process从提升/作为管理员进程运行非提升的子进程
【发布时间】:2015-07-20 16:19:06
【问题描述】:

我的应用程序通过另一个名为“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.Settingsuser-sensivite 对象。

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

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

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

现在谢谢。

【问题讨论】:

  • 如果你想走那条路,它不会那么容易,thisthis 应该让你通过 p/invoke 的方式如果你真的想,它也建议另一个解决方案正在运行非提升进程以在之后启动更新的应用程序。
  • 感谢您的链接!我想最简单的方法是您提供的第一个链接中的第二个答案。在运行更新程序之前从主应用程序运行另一个 exe(让我们说“autorestarter.exe”)是一个非常好的主意。所有“autorestarter”应该做的是等待“updater”进程完成(每1秒检查一次),当它结束时,再次启动主应用程序。最简单的解决方案。谢谢。
  • 您是否已经在主应用中尝试过<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
  • @RoniTovi 在这种情况下你可以使用 Process.WaitForExit() 。

标签: vb.net uac privileges runas my.settings


【解决方案1】:

“取消提升”子进程的一种方法是通过资源管理器启动它。这应该一般适用于普通 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 也是如此。

【讨论】:

  • 您可能还应该检查完整性级别,而不仅仅是“是管理员”。可以创建一个没有管理员访问权限但仍以高完整性级别运行的子进程。真正的非提升过程具有中等完整性级别。 Process Hacker 可以显示给定进程的完整性级别。不能说这种方法是否能做到这一点。有一种(真正丑陋的 P/Invoke C#)方法可以启动不依赖于 Explorer 未提升的非提升子进程 - 请参阅 here
猜你喜欢
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2011-04-25
  • 2015-06-16
  • 1970-01-01
  • 2014-08-20
  • 2022-11-22
  • 2014-04-30
相关资源
最近更新 更多