从Console或Windows服务以编程方式创建Windows会话

如何以编程方式登录到Windows以创建Windows登录会话? 我需要一种适用于WinForms应用程序,来自Console应用程序以及(最重要的)来自Windows服务的方法。

另一个要求是我需要它来运行程序/服务运行的本地系统以及远程系统。

如果有办法使用pInvoke / Win32 API执行此操作,我也会对此持开放态度。

我在研究中发现了类似的问题/答案:

以编程方式创建和启动RDP会话(没有gui)

这里的答案说它是可能的但是提供了一个链接,但链接中的示例代码不起作用

通过Win32 API从服务创建Windows会话

没有解决问题的方法

以编程方式创建Windows会话

没有解决方案,但在http://freerdp.com为他工作的评论中提到了OP。

我创建了一个简单的实用程序,我相信它符合问题中的所有要求。 您需要向Microsoft终端服务Active Client 1.0类型库(ActiveX)添加COM引用。

我认为它可能无法在本地计算机上创建会话,但我在2012R2中作为服务运行测试,它实际上可以。 可以从WinForms应用程序或控制台应用程序调用相同的确切方法。 从WinForms或Console应用程序启动时,表单会显示几秒钟,因此我确保将控件设置为enabled = false,以便无法与之交互。

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

在旁注中我发现这个问题说可能有一种方法可以使用ActiveX控件(对于RDP)而根本不使用Windows窗体。 我看到了他们给出的例子,我不确定在这种情况下使用他们的代码。

没有表单的ActiveX控件

如果有人在没有在表单上托管ActiveX控件的情况下了解如何执行此操作,请发布示例。