Create Windows session programmatically

喜夏-厌秋 提交于 2019-12-03 09:31:31

AFAIK, you cannot create sessions programmably. The client would have to connect to the machine using Terminal Services or Remote Desktop for that. You can, however, programmably log in to a user account and impersonate it if you just need to run a process as that user without making it visible to the screen. Look at LogonUser() and ImpersonateLoggedOnUser(), CreateProcessAsUser(), or CreateProcessWithLogonW().

@WolfgangZiegler, I know this is an old question but I've actually found a solution for you! I've written a simple utility using the Remote Desktop ActiveX control (COM Reference). If you paste this code into a Class Library you can then call it by simply passing in the server, username, domain, and password and everything is done for you without any other interaction required. That answers the question you asked, but you also mentioned that you need to start an application into the session you just created. I know you didn't directly ask about that but I thought I'd point you in the right direction just in case since your situation sounds very similar to mine. There are actually several ways to launch an application so you'll need to find the right one for you. You'll need to use Win32 API to create a process most likely with either CreateProcessAsUser, CreateProcessWithLogon, or with CreateProcessWithToken. All three of these methods are in Advapi32.dll.

I've written this RDP utility in a way so that you could call it every time but initiating an RDP session takes several seconds so for performance sake I'd suggest you write another method to enumerate the sessions and see if your user is logged in and only call this utility when you determine that your user isn't logged in (That's what I did in my actual project).

Here's a link back to my question that has a few more requirements/details than this question.

Create Windows Session programmatically from Console or Windows Service

And here's my RDP utility. If you put this code in a class library you can then call it from a console app, winForms app, or from a windows service.

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);
        }
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!