c# - 从控制台或 Windows 服务以编程方式创建 Windows session

标签 c# winforms windows-services activex rdp

如何以编程方式登录到 Windows 以创建 Windows 登录 session ? 我需要一种适用于 WinForms 应用程序、控制台应用程序和(最重要的)Windows 服务的方法。

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

如果有办法使用 pInvoke/Win32 API 来做到这一点,我也愿意接受。

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

Programmatically create and launch and RDP session (without gui)

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

Create a Windows Session from a service via the Win32 API

所问问题无解

Create Windows session programmatically

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

最佳答案

我创建了一个简单的实用程序,我相信它可以满足问题中的所有要求。您需要添加对 Microsoft 终端服务事件客户端 1.0 类型库 (ActiveX) 的 COM 引用。

我认为它可能无法在本地计算机上创建 session ,但我在 2012R2 中作为服务运行进行了测试,它实际上可以。可以从 WinForms 应用程序或控制台应用程序调用完全相同的方法。从 WinForms 或控制台应用程序启动时,表单会显示几秒钟,因此我确保将控件设置为 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);
        }
    }
}

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

ActiveX control without a form

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

关于c# - 从控制台或 Windows 服务以编程方式创建 Windows session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52801093/

相关文章:

c# - SaveFileDialog 设置默认路径和文件类型?

C# - Windows 服务中的多个计时器

c# - 如何在 Windows 服务中连续读取文本文件

c# - 一行if语句,如何转换这个if-else-statement

c# - 更新每个选定的 datagridview 行

c# - Windows 窗体设计器 - 自动在类前面添加命名空间

c# - 如何创建作为独立 exe 应用程序的 Windows 服务?

c# - 如何在Unity 3D中使音频静音?

c# - 以编程方式将应用程序池分配给iis7中的网站

c# - 如何将 "123"添加到字符串的开头并将其填充为正好 12 个字符?