本文介绍了CreateProcessAsUser与ShellExecute的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要以另一个用户的身份使用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);

将仅以登录用户而不是其他用户"的身份启动calc

@ 1800信息:CreateProcess/CreateProcessAsUserShellExecute不同,对于Vista上的UAC,当您无法控制用户正在执行的程序时,CreateProcess是无用的(如果您给它一个带有清单文件标记为requireAdmin的exe文件,则会返回错误消息

@Brian R. Bondy:我已经知道此信息了(不要误会我,这是很好的东西),但是我要求的是ShellExecuteAsUser,这与主题无关(IMHO),而不是关于启动进程的问题另一个用户,我已经知道该怎么做.

解决方案

该解决方案实际上取决于您的需求,并且可能非常复杂(完全感谢Windows Vista).这可能超出了您的需求,但这将帮助其他通过搜索找到此页面的人.

  1. 如果您不需要使用GUI来运行该过程,并且不需要提升
  2. 如果您要运行的用户已经登录到会话中
  3. 如果您需要使用GUI运行该过程,并且该用户可能登录或可能未登录
  4. 如果您需要使用海拔高度运行该过程

关于1:在Windows Vista中,存在一种称为会话0隔离的东西.所有服务均以会话0运行,并且您不应该在会话0中使用GUI.第一个登录的用户已登录到会话1.在早期版本的Windows(Vista之前的版本)中,第一个登录的用户也已在该版本中完全运行.会话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签名过程来使其正常工作.您要启动的进程还必须具有与清单文件关联的清单文件,该清单文件与所请求的ExecutionLevel level ="requireAdministrator"

其他说明:

  • 您可以通过SetTokenInformation和TokenSessionId设置令牌的会话
  • 您无法更改已经运行的进程的会话ID.
  • 如果Vista不在考虑范围之内,那么整个过程将大大简化.

I need to ShellExecute something as another user, currently I start a helper process with CreateProcessAsUser that calls ShellExecute, but that seems like too much of a hack (Wrong parent process etc.) Is there a better way to do this?

@PabloG: ImpersonateLoggedOnUser does not work:

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);

will just start calc as the logged in user, not "otheruser"

@1800 INFORMATION: CreateProcess/CreateProcessAsUser is not the same as ShellExecute, with UAC on Vista, CreateProcess is useless when you don't have control over what program the user is executing (CreateProcess will return with a error if you give it a exe file with a manifest marked as requireAdmin)

@Brian R. Bondy: I already know this info (And don't get me wrong, its good stuff), but it is off topic (IMHO) I am asking for a ShellExecuteAsUser, not about starting processes as another user, I already know how to do that.

解决方案

The solution really depends on what your needs are, and can be pretty complex (Thanks fully to Windows Vista). This is probably going to be beyond your need, but this will help others that find this page via search.

  1. If you do not need the process to run with a GUI and you do not require elevation
  2. If the user you want to run as is already logged into a session
  3. If you need to run the process with a GUI, and the user may, or may not be logged in
  4. If you need to run the process with elevation

Regarding 1:In windows Vista there exists something called session 0 isolation. All services run as session 0 and you are not supposed to have a GUI in session 0. The first logged on user is logged into session 1. In previous versions of windows (pre Vista), the first logged on user was also ran fully in session 0.

You can run several different processes with different usernames in the same session. You can find a good document about session 0 isolation here.

Since we're dealing with option 1), you don't need a GUI. Therefore you can start your process in session 0.

You'll want a call sequence something like this:LogonUser, ExpandEnvironmentStringsForUser, GetLogonSID, LoadUserProfile, CreateEnvironmentBlock, CreateProcessAsUser.

Example code for this can be found via any search engine, or via Google code search

Regarding 2: If the user you'd like to run the process as is already logged in, you can simply use: WTSEnumerateSessions, and WTSQuerySessionInformation to get the session ID, and then WTSQueryUserToken to get the user token. From there you can just use the user token in the CreateProcessAsUser Win32 API.

This is a great method because you don't even need to login as the user nor know the user's username/password. I believe this is only possible via a service though running as local system account.

You can get the current session via WTSGetActiveConsoleSessionId.

Regarding 3:You would follow the same steps as #1, but in addition you would use the STARTUPINFO's lpDesktop field. Set this to winsta0\Default. You will also need to try to use the OpenDesktop Win32 API and if this fails you can CreateDesktop. Before using the station and desktop handles you should use SetSecurityInfo on each of them with SE_WINDOW_OBJECT, and GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION.

If the user in question later tries to login, he will actually see the running process.

Regarding 4:This can be done as well, but it requires you to already be running an elevated process. A service running as local system account does run as elevated. I could also only get it to work by having an authenticode signed process that I wanted to start. The process you want to start also must have a manifest file associated with it with the requestedExecutionLevel level="requireAdministrator"

Other notes:

  • You can set a token's session via SetTokenInformation and TokenSessionId
  • You cannot change the session ID of an already running process.
  • This whole process would be drastically more simple if Vista was not in the equation.

这篇关于CreateProcessAsUser与ShellExecute的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-21 03:20