通过控制台或Windows服务以编程方式创建Windows会话 [英] Create Windows Session programmatically from Console or Windows Service

查看:377
本文介绍了通过控制台或Windows服务以编程方式创建Windows会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何以编程方式登录Windows以创建Windows登录会话?
我需要一种可以从WinForms应用程序,控制台应用程序以及(最重要的)Windows服务中使用的方法。

How can I programmatically log in to windows to create a Windows Logon Session? I need a way that works from a WinForms app, from a Console app, and (most important) from a Windows Service.

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

One other requirement is that I need it to work on a the local system that the program/service is running on and also for remote systems.

如果可以使用pInvoke / Win32做到这一点API我也对此持开放态度。

If there's a way to do this using pInvoke/Win32 API I am open to that too.

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

I found these similar questions/answers in my research:

< a href = https://stackoverflow.com/questions/2767035/programmatically-create-and-launch-and-rdp-session-without-gui>以编程方式创建和启动以及RDP会话(无gui)

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

The answer here says it's possible but and gives a link but the sample code from the link doesn't work

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

没有解决方案n问

以编程方式创建Windows会话

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

No Solution but the OP mentioned in a comment that http://freerdp.com worked for him.

推荐答案

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

I've created a simple utility that I believe meets all the requirements in the question. You'll need to add a COM reference to Microsoft Terminal Services Active Client 1.0 Type Library (ActiveX).

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

I thought it might not work for creating a session on the local machine but I tested in in 2012R2 running as a Service and it actually can. The same exact method can be called from a WinForms app or from a Console app. When launched from a WinForms or Console app, the a form is shown for a few seconds so I made sure to set the control to enabled = false so it can't be interacted with.

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窗体。我看到了他们给出的示例,但不确定是否可以在这种情况下使用他们的代码。

On a side note I found this question that says there may be a way to use the ActiveX control (for RDP) without using a windows form at all. I saw the example they gave and I was unsure hot to use their code for this situation.

不带表单的ActiveX控件

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

If there's anyone out there who understands how to do this without hosting the ActiveX control on a Form please post an example.

这篇关于通过控制台或Windows服务以编程方式创建Windows会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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