我们有一个附带清单的程序和选项“level =”requireAdministrator“。 在标准用户(不是管理员)下启动程序后,它升级到管理员用户并从那时起SHGetFolderPath(0,CSIDL_LOCAL_APPDATA,0,SHGFP_TYPE_CURRENT,@ buf))返回管理员本地目录,但不返回用户最初启动的位置。 当然我们可以将标准用户令牌作为第三个参数传递给SHGetFolderPath,但我们如何在升级程序中获取它? 有没有办法做到这一点?
当然,由于这个问题,我们还有另外一个问题。如何使用ShellExecute启动另一个程序而不是作为提升程序中的管理员?当然我们可以使用CreateProcessWithTokenW,但仍存在令牌问题(如何获取此令牌)。 现在我们正在寻找IShellDispatch2接口并尝试使用资源管理器启动应用程序而不是管理员,但有些东西告诉我这是错误的方法。
我知道我们必须以标准用户身份启动程序,然后使用com对象仅提升应该使用管理员权限执行的部分代码。但是,主要问题仍然是令牌。
还有一个想法是使用“level =”asInvoker“制作清单”并以标准用户身份启动第一个程序,检测所有本地用户路径并将其作为参数传递给ShellExecuteEx,使用runas和SEE_MASK_NOCLOSEPROCESS选项并运行相同的程序,但是管理员。升级程序退出后,我们可以执行任何来自未提升程序的程序,而不是管理员。这是正确的吗?
答案 0 :(得分:1)
来自Raymond Chen:
How can I launch an unelevated process from my elevated process and vice versa?
从一个不高尚的流程转变为一个升级的流程很容易。您可以使用passing the runas verb高程运行ShellExecute或ShellExecuteEx。
走另一条路比较棘手。首先,很难让你的令牌正确地去除高程性质。而另一方面,即使你能做到这一点,也不是正确的事情,因为没有提升的用户可能与提升的用户不同。
此处的解决方案是返回资源管理器并请求Explorer为您启动该程序。由于资源管理器作为原始的非高级用户运行,因此该程序将作为原始的非高级用户运行。
我试图将代码从C ++中翻译出来,但管理起来太过毛茸茸。
简短版本是:它非常难。
答案 1 :(得分:1)
也许有点晚了,但你的另类选择是正确的方法。一旦程序升级,没有可靠的方法来启动另一个程序,但没有提升,甚至知道用户启动它,如果它是使用不同的凭据完成的。
所有这些问题的一般解决方案是将程序分成两个不同的过程(可以在1或2个不同的.EXE中实现,如您所愿)。 “主”程序,即用户运行的程序,运行而不是提升,表现为asInvoker
,然后又启动第二个“工作”进程,表现为{{1} }。主要的一个可以通过命令行,未命名的管道,窗口消息或任何其他形式的IPC将数据从原始用户传递到第二个用户,而工作进程只执行所有管理员工作。可能您需要在产生另一个非提升程序的时候通知主进程。