我需要ShellExecute
作为另一个用户的东西,目前我开始使用CreateProcessAsUser
该调用的辅助进程ShellExecute
,但这似乎太多的黑客(错误的父进程等)有没有更好的方法来做到这一点?
@PabloG:ImpersonateLoggedOnUser不起作用:
HANDLE hTok; VERIFY(LogonUser("otheruser",0,"password",LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hTok)); VERIFY(ImpersonateLoggedOnUser(hTok)); ShellExecute(0,0,"calc.exe",0,0,SW_SHOW); RevertToSelf(); CloseHandle(hTok);
将以登录用户开始计算,而不是"其他用户"
@ 1800信息:CreateProcess
/ 与Vista上的UAC CreateProcessAsUser
不一样ShellExecute
,CreateProcess
当你无法控制用户正在执行的程序时,它是无用的(CreateProcess
如果你给它一个带有标记为清单的清单的exe文件,则会返回错误requireAdmin)
@Brian R. Bondy:我已经知道这个信息(并且不要误解我的好东西),但这是关于主题(恕我直言)我要求的ShellExecuteAsUser
,不是关于作为另一个用户启动进程,我已经知道了怎么做.
解决方案实际上取决于您的需求,并且可能非常复杂(完全归功于Windows Vista).这可能超出了您的需要,但这将有助于通过搜索找到此页面的其他人.
如果您不需要使用GUI运行该过程,并且不需要提升
如果要运行的用户已登录到会话中
如果您需要使用GUI运行该过程,并且该用户可能或可能未登录
如果需要使用高程运行该过程
关于1: 在Windows Vista中存在称为会话0隔离的东西.所有服务都作为会话0运行,并且您不应该在会话0中使用GUI.首先登录的用户登录到会话1.在以前版本的Windows(Vista之前)中,第一个登录用户也完全运行会话0.
您可以在同一会话中使用不同的用户名运行多个不同的进程.您可以在此处找到有关会话0隔离的好文档.
由于我们正在处理选项1),因此您不需要GUI.因此,您可以在会话0中启动您的流程.
你需要一个这样的调用序列:LogonUser,ExpandEnvironmentStringsForUser,GetLogonSID,LoadUserProfile,CreateEnvironmentBlock,CreateProcessAsUser.
可以通过任何搜索引擎或Google代码搜索找到此示例代码
关于2: 如果您希望运行该进程的用户已经登录,您只需使用:WTSEnumerateSessions和WTSQuerySessionInformation来获取会话ID,然后使用WTSQueryUserToken来获取用户令牌.从那里,您可以在CreateProcessAsUser Win32 API中使用用户令牌.
这是一个很好的方法,因为您甚至不需要以用户身份登录也不需要知道用户的用户名/密码.我相信这只能通过运行本地系统帐户的服务来实现.
您可以通过WTSGetActiveConsoleSessionId获取当前会话.
关于3: 您将遵循与#1相同的步骤,但此外您将使用STARTUPINFO的lpDesktop字段.将其设置为winsta0\Default.您还需要尝试使用OpenDesktop Win32 API,如果失败,您可以使用CreateDesktop.在使用工作站和桌面控制台之前,您应该使用SE_WINDOW_OBJECT和GROUP_SECURITY_INFORMATION |中的每一个使用SetSecurityInfo.DACL_SECURITY_INFORMATION.
如果有问题的用户稍后尝试登录,他将实际看到正在运行的进程.
关于4: 这也可以这样做,但它要求你已经在运行升级过程.作为本地系统帐户运行的服务确实以提升的方式运行.我也可以通过我想要启动的authenticode签名进程来使它工作.您要启动的进程还必须具有与其关联的清单文件,并且requestedExecutionLevel level ="requireAdministrator"
其他说明:
您可以通过SetTokenInformation和TokenSessionId设置令牌的会话
您无法更改已在运行的进程的会话ID.
如果Vista不在等式中,整个过程将变得非常简单.