在启动用户会话的过程从服务 [英] Launching a process in user’s session from a service

查看:149
本文介绍了在启动用户会话的过程从服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Windows Vista / 7/2008 / 2008R2,它是在所有可能从服务于用户的会话启动一个进程?具体来说,本地会议将是最有用的。

一切我一直在阅读似乎是说这是不可能的,但我想我会问这里完全放弃了。

我编码在VB.NET,但会采取任何建议。


解决方案

这是真的有可能。您具有的主要问题是,Windows应该被看作是一个终端服务器和用户会话的远程会话。您的服务应该能够开始运行其在远程会话属于用户的过程。

顺便说一句,如果你写这下不添加到域和快速用户切换激活Windows XP上运行一个服务,你可以有相同的问题,并在第二次运行启动一个进程(第三和等等)登录用户的桌面。

我希望你有一个用户令牌,您收到例如关于假冒或您届有一个 dwSessionId 。如果没有它,你可以尝试使用一些WTS-功能(远程桌面服务API <一个href=\"http://msdn.microsoft.com/en-us/library/aa383464.aspx\">http://msdn.microsoft.com/en-us/library/aa383464.aspx,例如 WTSEnumerateProcesses WTSGetActiveConsoleSessionId )或LSA-API,找出相应的用户会话( LsaEnumerateLogonSessions 看<一个href=\"http://msdn.microsoft.com/en-us/library/aa378275.aspx\">http://msdn.microsoft.com/en-us/library/aa378275.aspx和 LsaGetLogonSessionData 看<一个href=\"http://msdn.microsoft.com/en-us/library/aa378290.aspx\">http://msdn.microsoft.com/en-us/library/aa378290.aspx)或 ProcessIdToSessionId (见<一href=\"http://msdn.microsoft.com/en-us/library/aa382990.aspx\">http://msdn.microsoft.com/en-us/library/aa382990.aspx).

您可以使用 GetTokenInformation 函数参数 TokenSessionId (见<一href=\"http://msdn.microsoft.com/en-us/library/aa446671.aspx\">http://msdn.microsoft.com/en-us/library/aa446671.aspx)接收会话ID dwSessionId 如果您知道用户令牌 hClient

用户会话

  BOOL bSuccess;
HANDLE hProcessToken = NULL,hNewProcessToken = NULL;
DWORD dwSessionId,cbReturnLength;bSuccess = GetTokenInformation(hClient,TokenSessionId,&安培; dwSessionId,
                                的sizeof(DWORD),放大器; cbReturnLength);
bSuccess = OpenProcessToken(GetCurrentProcess(),MAXIMUM_ALLOWED,&放大器; hProcessToken);
bSuccess = DuplicateTokenEx(hProcessToken,MAXIMUM_ALLOWED,NULL,
                             SecurityImpersonation,
                             TokenPrimary,&安培; hNewProcessToken);
EnablePrivilege(​​SE_TCB_NAME);
bSuccess = SetTokenInformation(hNewProcessToken,TokenSessionId,&安培; dwSessionId,
                                的sizeof(DWORD));
bSuccess = CreateProcessAsUser(hNewProcessToken,NULL,szCommandToExecute,...);

这code只是一个架构。 EnablePrivilege 是用一个简单的函数 AdjustTokenPrivileges 启用 SE_TCB_NAME 特权(见<一href=\"http://msdn.microsoft.com/en-us/library/aa446619.aspx\">http://msdn.microsoft.com/en-us/library/aa446619.aspx作为模板)。从你的过程中开始你有TCB特权的过程是很重要的,但如果在本地系统下运行的服务,你有足够的权限。顺便说一下,以下$ C $不仅本地系统帐户C的片段工作,但户口必须有 SE_TCB_NAME 荣幸能够切换当前终端服务器会话。

还有一个的话。在code以上,我们开始新的进程具有相同的帐户作为当前进程具有(例如本地系统)。您可以更改更改code使用另一个帐户,例如用户令牌 hClient 。有一个这是唯一重要的主令牌。如果你有一个模拟令牌你可以把它转换成主令牌酷似在code以上。

CreateProcessAsUser 使用了 STARTUPINFO 结构,你应该使用 lpDesktop = WinSta0 \\默认。

您的要求,它可以也需要使用 CreateEnvironmentBlock 以创建你将被传递到新的进程中新的环境块。

依靠

我建议你也读<一个href=\"http://stackoverflow.com/questions/3100934/how-to-ensure-process-window-launched-by-process-startprocessstartinfo-has-focu/3101061#3101061\">How以确保的Process.Start(的ProcessStartInfo)推出了工艺窗口拥有所有形式的焦点?,我将描述如何迫使这一进程将在用户桌面上的前景启动。

In Windows Vista/7/2008/2008R2, is it at all possible to launch a process in a user's session from a service? Specifically, the local session would be most useful.

Everything I've been reading seems to say this isn't possible, but I figured I'd ask here before giving up completely.

I'm coding in VB.NET, but will take suggestions in anything.

解决方案

It is really possible. The main problem which you have is that Windows should be seen as a terminal server and a users session as a remote session. Your service should be able to start a process which run in the remote session belongs to the user.

By the way, if you write a service which run under Windows XP which is not added to a domain and the fast user switching is activated, you can have the same problems to start a process on running on the second (third and so on) logged users desktop.

I hope you have a user token, which you receive for example with respect of impersonation or you have a dwSessionId of session. If you don't have it you can try use some WTS-function (Remote Desktop Services API http://msdn.microsoft.com/en-us/library/aa383464.aspx, for example WTSEnumerateProcesses or WTSGetActiveConsoleSessionId) or LSA-API to find out the corresponding users session (LsaEnumerateLogonSessions see http://msdn.microsoft.com/en-us/library/aa378275.aspx and LsaGetLogonSessionData see http://msdn.microsoft.com/en-us/library/aa378290.aspx) or ProcessIdToSessionId (see http://msdn.microsoft.com/en-us/library/aa382990.aspx).

You can use GetTokenInformation function with the parameter TokenSessionId (see http://msdn.microsoft.com/en-us/library/aa446671.aspx) to receive the session id dwSessionId of the users session if you knows the users token hClient.

BOOL bSuccess;
HANDLE hProcessToken = NULL, hNewProcessToken = NULL;
DWORD dwSessionId, cbReturnLength;

bSuccess = GetTokenInformation (hClient, TokenSessionId, &dwSessionId,
                                sizeof(DWORD), &cbReturnLength);
bSuccess = OpenProcessToken (GetCurrentProcess(), MAXIMUM_ALLOWED, &hProcessToken);
bSuccess = DuplicateTokenEx (hProcessToken, MAXIMUM_ALLOWED, NULL,
                             SecurityImpersonation,
                             TokenPrimary, &hNewProcessToken);
EnablePrivilege (SE_TCB_NAME);
bSuccess = SetTokenInformation (hNewProcessToken, TokenSessionId, &dwSessionId,
                                sizeof(DWORD));
bSuccess = CreateProcessAsUser (hNewProcessToken, NULL, szCommandToExecute, ...);

This code only a schema. EnablePrivilege is a simple function used AdjustTokenPrivileges to enable SE_TCB_NAME privilege (see http://msdn.microsoft.com/en-us/library/aa446619.aspx as a template). It is important that the process from which you are start a process you have TCB privilege, but if your service run under the Local System you have enough permissions. By the way, following code fragment work with not only Local System account, but the account must have SE_TCB_NAME privilege to be able to switch current terminal server session.

One more remark. In the code above we start new process with the same account as the current process have (for example Local System). You change change a code to use another account for example the users token hClient. It is only important to have a primary token. If you have an impersonation token you can convert it to the primary token exactly like in the code above.

In the STARTUPINFO structure used in CreateProcessAsUser you should use lpDesktop = WinSta0\Default".

Depend on your requirements it could be also needed to use CreateEnvironmentBlock to create an new environment block that you will be passing to the new process.

I recommend you also to read How to ensure process window launched by Process.Start(ProcessStartInfo) has focus of all Forms? where I describe how to force that the process will be started in foreground on the users desktop.

这篇关于在启动用户会话的过程从服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆