我在Windows服务(0)会话中运行了一项服务。 从客户端连接后,我需要为给定的用户凭据创建一个新的Windows会话,登录该用户并启动应用程序进入这个新会话。
有没有办法以编程方式为给定的用户凭据创建用户会话?
答案 0 :(得分:4)
AFAIK,您无法以可编程方式创建会话。客户端必须使用终端服务或远程桌面连接到计算机。但是,如果您只需要以该用户身份运行流程而不将其显示在屏幕上,则可以以可编程方式登录到用户帐户并模拟它。查看LogonUser()
和ImpersonateLoggedOnUser()
,CreateProcessAsUser()
或CreateProcessWithLogonW()
。
答案 1 :(得分:1)
@WolfgangZiegler,我知道这是一个老问题,但实际上为您找到了解决方案!我已经使用远程桌面ActiveX控件(COM参考)编写了一个简单的实用程序。如果将此代码粘贴到类库中,则可以通过简单地传入服务器,用户名,域和密码来调用它,并且一切都为您完成,而无需任何其他交互。这可以回答您提出的问题,但是您还提到需要在刚创建的会话中启动应用程序。我知道您没有直接询问这个问题,但我想我会向您指出正确的方向,以防万一您的情况听起来与我的情况非常相似。实际上,有几种启动应用程序的方法,因此您需要为您找到合适的应用程序。您将需要使用Win32 API来最有可能通过CreateProcessAsUser,CreateProcessWithLogon或CreateProcessWithToken创建一个进程。这三种方法都在Advapi32.dll中。
我已经以某种方式编写了此RDP实用程序,以便您每次都可以调用它,但是启动RDP会话需要花费几秒钟的时间,因此出于性能考虑,我建议您编写另一种枚举会话并查看用户是否已登录,只有在确定用户未登录时才调用此实用程序(这就是我在实际项目中所做的事情)。
这是一个指向我的问题的链接,该链接比该问题有更多的要求/细节。
Create Windows Session programmatically from Console or Windows Service
这是我的RDP实用程序。如果将此代码放在类库中,则可以从控制台应用程序,winForms应用程序或Windows服务调用它。
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using AxMSTSCLib;
namespace Utility.RemoteDesktop
{
public class Client
{
private int LogonErrorCode { get; set; }
public void CreateRdpConnection(string server, string user, string domain, string password)
{
void ProcessTaskThread()
{
var form = new Form();
form.Load += (sender, args) =>
{
var rdpConnection = new AxMSTSCLib.AxMsRdpClient9NotSafeForScripting();
form.Controls.Add(rdpConnection);
rdpConnection.Server = server;
rdpConnection.Domain = domain;
rdpConnection.UserName = user;
rdpConnection.AdvancedSettings9.ClearTextPassword = password;
rdpConnection.AdvancedSettings9.EnableCredSspSupport = true;
if (true)
{
rdpConnection.OnDisconnected += RdpConnectionOnOnDisconnected;
rdpConnection.OnLoginComplete += RdpConnectionOnOnLoginComplete;
rdpConnection.OnLogonError += RdpConnectionOnOnLogonError;
}
rdpConnection.Connect();
rdpConnection.Enabled = false;
rdpConnection.Dock = DockStyle.Fill;
Application.Run(form);
};
form.Show();
}
var rdpClientThread = new Thread(ProcessTaskThread) { IsBackground = true };
rdpClientThread.SetApartmentState(ApartmentState.STA);
rdpClientThread.Start();
while (rdpClientThread.IsAlive)
{
Task.Delay(500).GetAwaiter().GetResult();
}
}
private void RdpConnectionOnOnLogonError(object sender, IMsTscAxEvents_OnLogonErrorEvent e)
{
LogonErrorCode = e.lError;
}
private void RdpConnectionOnOnLoginComplete(object sender, EventArgs e)
{
if (LogonErrorCode == -2)
{
Debug.WriteLine($" ## New Session Detected ##");
Task.Delay(10000).GetAwaiter().GetResult();
}
var rdpSession = (AxMsRdpClient9NotSafeForScripting)sender;
rdpSession.Disconnect();
}
private void RdpConnectionOnOnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
{
Environment.Exit(0);
}
}
}