繁体   English   中英

通过服务在用户会话中启动流程

[英]Launching a process in user’s session from a service

在Windows Vista / 7/2008 / 2008R2中,是否可以通过服务在用户会话中启动进程? 具体来说,本地会话将是最有用的。

我读过的所有内容似乎都说这是不可能的,但我想我会在完全放弃之前先问一下这里。

我在VB.NET中进行编码,但会在任何方面提出建议。

确实有可能。 您遇到的主要问题是Windows应该被视为终端服务器,而用户会话应该被视为远程会话。 您的服务应该能够启动一个在远程会话中运行的属于用户的进程。

顺便说一句,如果编写的服务未在Windows XP下运行,并且未添加到域中,并且激活了快速用户切换,则在第二个(第三个)上运行该进程时,可能会遇到相同的问题。登录的用户桌面。

我希望您有一个用户令牌,例如,您可以收到模拟用户令牌或会话的dwSessionId 如果没有,则可以尝试使用某些WTS功能(远程桌面服务API http://msdn.microsoft.com/zh-cn/library/aa383464.aspx ,例如WTSEnumerateProcessesWTSGetActiveConsoleSessionId )或LSA-API找出相应的用户会话( LsaEnumerateLogonSessions请参见http://msdn.microsoft.com/zh-cn/library/aa378275.aspx,LsaGetLogonSessionData请参见http://msdn.microsoft.com/zh-cn/library/aa378290。 aspx )或ProcessIdToSessionId (请参阅http://msdn.microsoft.com/zh-cn/library/aa382990.aspx )。

如果您知道用户令牌hClient则可以将GetTokenInformation函数与参数TokenSessionId (请参阅http://msdn.microsoft.com/zh-cn/library/aa446671.aspx )以接收用户会话的会话ID dwSessionId

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

此代码仅是架构。 EnablePrivilege是一个简单的函数,用于AdjustTokenPrivileges以启用SE_TCB_NAME特权(请参阅http://msdn.microsoft.com/zh-cn/library/aa446619.aspx作为模板)。 拥有启动TCB特权的过程非常重要,但是,如果您的服务在本地系统下运行,则您具有足够的权限。 顺便说一句,以下代码片段不仅适用于本地系统帐户,而且该帐户必须具有SE_TCB_NAME特权才能切换当前的终端服务器会话。

再说一遍。 在上面的代码中,我们使用与当前进程相同的帐户启动新进程(例如本地系统)。 您更改更改代码以使用另一个帐户,例如用户令牌hClient 拥有primary token仅是重要的。 如果您有模拟令牌,则可以将其完全转换为主要令牌,就像上面的代码一样。

CreateProcessAsUser使用的STARTUPINFO结构中,应使用lpDesktop = WinSta0 \\ Default”。

根据您的要求,可能还需要使用CreateEnvironmentBlock创建要传递给新流程的新环境块。

我还建议您阅读如何确保由Process.Start(ProcessStartInfo)启动的进程窗口具有所有窗体的焦点? 在这里,我描述了如何强制该过程将在用户桌面的前台启动。

如果有帮助,我会遇到类似的问题,但需要一个纯Powershell解决方案。

我将其他网站的内容拼凑而成,并提出了以下建议:

function Invoke-CommandInSession 
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [ScriptBlock] $expression
    )

    $commandLine = “powershell“

    ## Convert the command into an encoded command for PowerShell
    $commandBytes = [System.Text.Encoding]::Unicode.GetBytes($expression)
    $encodedCommand = [Convert]::ToBase64String($commandBytes)
    $args = “-Output XML -EncodedCommand $encodedCommand”


    $action = New-ScheduledTaskAction -Execute $commandLine -Argument $args
    $setting = New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter ([Timespan]::Zero)
    $trigger = New-ScheduledTaskTrigger -Once -At ((Get-Date) + ([Timespan]::FromSeconds(5)))
    $task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $setting
    Register-ScheduledTask "Invoke-CommandInSession - $([Guid]::NewGuid())" -InputObject $task
}

是的,这有点奇怪,但是可以用-最重要的是,您可以在ps远程处理中调用它

是的,您可以使用CreateProcessAsUser执行此操作。 MSDN上有示例文章,并且有一些警告。

可以这样做,但是将服务直接与用户会话进行交互不是很好的做法,因为它可能会造成严重的安全漏洞。

http://support.microsoft.com/kb/327618

更好的方法是创建两个程序,一个后端服务和一个前端客户端UI程序。 服务后端一直运行,并使用WCF公开其操作(例如)。 客户端程序可以在用户会话启动时运行。

颠覆32位和64位架构中的Vista UAC

提供的代码针对Vista,但也适用于Win7和Win10

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM