Winapi 从非交互式服务(win32/.net/powershell)启动UAC提升进程
我正在使用第三方Windows服务,它通过使用CreateProcessAsUser()运行脚本和可执行文件来处理一些自动化任务。由于UAC和通过API处理LUA提升的方式,我在Windows Server 2008上遇到了问题 该服务以LocalSystem运行,未启用“与桌面交互”。这些进程是作为Administrators组中的用户运行的,而不是作为Administrator帐户运行的(该帐户不受许多UAC限制)。所有UAC默认设置均已就位 我可以向服务传递任意命令或powershell代码,但我似乎无法“突破”服务启动的非提升、非交互过程 问题的关键似乎是启动提升进程的唯一(公共)API选项是带有“runas”动词的ShellExecute(),但据我所知,它不能从非交互式服务调用,或者会出现类似“此操作需要交互式窗口站”的错误 我发现的唯一解决方法如下所述: 在Vista中,官方记录的方式 提升流程只需使用 shell API ShellExecute(Ex)(非 CreateProcess或CreateProcessAsUser)。 因此,您的应用程序必须调用 ShellExecute(Ex)以启动帮助程序 提升为调用SendInput。 此外,由于会话0 隔离,服务只能使用 CreateProcessAsUser或 CreateProcessWithLogonW(无法使用 ShellExecute(Ex))来指定 交互式桌面 …我认为没有直接的方法 从中派生提升的进程 windows服务。我们只能先用 CreateProcessAsUser或 CreateProcessWithLogonW生成一个 将非提升进程导入到用户中 会话(交互式桌面)。然后在 对于非提升过程,可以使用 ShellExecute(Ex)生成提升的 实际任务的流程 要从.net/powershell代码中执行此操作,我似乎必须执行一些复杂的p/Invoke操作来调用CreateProcessAsUser或CreateProcessWithLogonW,因为.net System.Diagnostics.ProcessStartInfo没有可以设置为“winsta0\default”的lpDesktop的等效项。我不清楚LocalSystem是否有权调用CreateProcessAsUser或CreateProcessWithLogonW 我还看了 和 基于所有这些,我得出结论,没有直接的方法可以做到这一点。我错过什么了吗?这看起来真的不应该这么难。感觉上UAC从未被设计来处理非交互用例 如果有微软的人最终读到这篇文章,我注意到ShellExecute内部处理提升的方式是调用应用程序信息服务(AIS)。为什么不能通过一些Win32或.NET API调用AIS? 对不起,跑得有点长。谢谢你的建议。打破会话零隔离的“官方”方法是结合使用终端服务API和Winapi 从非交互式服务(win32/.net/powershell)启动UAC提升进程,winapi,uac,shellexecute,createprocessasuser,Winapi,Uac,Shellexecute,Createprocessasuser,我正在使用第三方Windows服务,它通过使用CreateProcessAsUser()运行脚本和可执行文件来处理一些自动化任务。由于UAC和通过API处理LUA提升的方式,我在Windows Server 2008上遇到了问题 该服务以LocalSystem运行,未启用“与桌面交互”。这些进程是作为Administrators组中的用户运行的,而不是作为Administrator帐户运行的(该帐户不受许多UAC限制)。所有UAC默认设置均已就位 我可以向服务传递任意命令或powershell代
CreateProcessAsUser()
在用户会话中启动进程。在我以前的工作中,我们就是这样做的,因为我们需要在安装下载的更新之前从服务向用户显示一个对话框,所以我知道它至少在WinXP、Win2K3、Vista和Win7上工作,但我不认为Win2K8会有太大的不同。基本上,过程如下:
WTSGetActiveConsoleSessionId()
以获取活动的控制台会话id(非常重要,因为交互式会话不总是会话1,即使在客户端系统上也是如此)。如果没有活动用户登录到交互式会话(即本地登录到物理机器,而不是使用RDP),此API也将返回-1WTSQueryUserToken()
,以获取一个打开的令牌,该令牌代表登录到控制台的用户DuplicateTokenEx()
将模拟令牌(从WTSQueryUserToken
)转换为主令牌CreateEnvironmentBlock()
为流程创建一个新环境(可选,但如果您不这样做,流程将没有新环境)createProcessAsUser()
的调用中。如果从步骤4创建了环境块,则还必须传递CREATE\u UNICODE\u environment
标志(始终)。这可能看起来很愚蠢,但如果不这样做,API会失败得很厉害(带有ERROR\u INVALID\u parameter
)DestroyEnvironmentBlock
,否则将产生内存泄漏。进程启动时会获得环境块的单独副本,因此您只销毁本地数据AdjustTokenPrivileges()
还原提升的(完整)令牌,但也不要引用我的话。但是,如MSDN文档中所述,请注意,不可能在尚未拥有特权的令牌上“添加”特权(例如,您不能通过使用AdjustTokenPrivileges
,将受限用户令牌转换为管理员;基础用户必须首先是管理员)
从技术上讲,从Win2K forward可以完成所有这一切。然而,这实际上只有从Wi开始才可行