How I can switch to different users desktops from windows service

94 Views Asked by At

I am trying to record a video of a user desktop when he logged in via RDP, the monitoring is based on the windows service onSessionChange event, due the nature of it then I am facing what is so called Session 0 isolation, so what I am looking for is how to switch to the logged in user in order to be able record his session?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceProcess;



namespace RdpMonitoringService
{
    struct RdpSession
    {
        public int sessionId;
        public string userName;
        public string ipAddress;
        public string sessionDateTime;
        public string recordFileName;
        public Recorder sessionRecorder;

        public string generateRecordFileName()
        {
            string dirName = "RecordedSessions";
            string path = AppDomain.CurrentDomain.BaseDirectory + "\\" + dirName;
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\" + dirName + "\\" + userName + " - " + sessionDateTime + ".mp4";
            return filepath;
        }

        public override string ToString()
        {
            return "SessionId: " + sessionId + ", userName: " + userName; 
        }
    }
    public partial class RdpMonitoringService : ServiceBase
    {
        RdpSession onRdpSession;
        Dictionary<int, RdpSession> rdpSessionList;
        public RdpMonitoringService()
        {
            InitializeComponent();

            this.CanPauseAndContinue = true;
            this.CanHandleSessionChangeEvent = true;

            rdpSessionList = new Dictionary<int, RdpSession>();
        }
        protected override void OnStart(string[] args)
        {
            WriteToFile("Service is started at: ============ " + DateTime.Now);
            WriteToFile("this.CanHandleSessionChangeEvent: " + this.CanHandleSessionChangeEvent);
        }
        protected override void OnStop()
        {
            WriteToFile("Service is stopped at " + DateTime.Now);
        }

        protected override void OnSessionChange(SessionChangeDescription sessionChangeDescription)
        {
            try { 
                var userInfo = TermServicesManager.GetSessionInfo(Dns.GetHostEntry("").HostName, sessionChangeDescription.SessionId);
                
                    IPAddress ipAddress = new IPAddress(userInfo.ClientAddress.Address.Skip(2).Take(4).ToArray());
                    if (!rdpSessionList.ContainsKey(sessionChangeDescription.SessionId))
                    {
                        onRdpSession.sessionId = sessionChangeDescription.SessionId;
                        onRdpSession.ipAddress = ipAddress.ToString();
                        onRdpSession.userName = userInfo.UserName;
                        onRdpSession.sessionDateTime = DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH'-'mm'-'ss");
                        onRdpSession.recordFileName = onRdpSession.generateRecordFileName();
                        //onRdpSession.sessionRecorder = Recorder.CreateRecorder();
                        //onRdpSession.sessionRecorder.Record(onRdpSession.generateRecordFileName());
                        rdpSessionList.Add(sessionChangeDescription.SessionId, onRdpSession);
                    }
                    else
                    {
                        onRdpSession = rdpSessionList[sessionChangeDescription.SessionId];
                    }


                    WriteToFile("SessionChange event");

                    switch (sessionChangeDescription.Reason)
                    {
                        case SessionChangeReason.SessionLogon:
                        case SessionChangeReason.RemoteConnect:
                        case SessionChangeReason.SessionUnlock:
                            WriteToFile("SessionChange" + DateTime.Now.ToLongTimeString() + ", SessionUnlock|RemoteConnect|SessionLogon [" + sessionChangeDescription.SessionId.ToString() + "]" + ", User: " + userInfo.UserName + ", Connect state: " + userInfo.ConnectState.ToString() + ", Client address: " + ipAddress.ToString() + ", user: " + userInfo.UserName + ", WinStationName: " + userInfo.WinStationName.ToString());
                            // Currently the bellow line crash the service because there is no desktop
                            // onRdpSession.sessionRecorder = new Recorder(new RecorderParams(onRdpSession.generateRecordFileName(), 60, SharpAvi.KnownFourCCs.Codecs.MotionJpeg, 70));
                        
                            // Switch to the user desktop based on his session id and start recording
                        break;
                        case SessionChangeReason.SessionLock:
                        case SessionChangeReason.SessionLogoff:
                        case SessionChangeReason.RemoteDisconnect:
                            WriteToFile("SessionChange: " + onRdpSession.ToString() + ", " + DateTime.Now.ToLongTimeString() + " RemoteDisconnect|SessionLogoff|SessionLock [" + sessionChangeDescription.SessionId.ToString() + "]" + ", User: " + userInfo.UserName + ", Connect state: " + userInfo.ConnectState.ToString() + ", Client address: " + ipAddress.ToString() + ", user: " + userInfo.UserName + ", WinStationName: " + userInfo.WinStationName.ToString());
                            onRdpSession.sessionRecorder.Dispose();
                            break;
                        default:
                                break;
                    }

            } 
            catch(Exception ex)
            {
                WriteToFile("SessionChange exception: " + ex.Message + " || " + sessionChangeDescription.SessionId.ToString() + " || " + onRdpSession.sessionId.ToString());

            }
        }

        public void WriteToFile(string Message)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\ServiceLog_" + DateTime.Now.Date.ToShortDateString().Replace('/', '_') + ".txt";
            if (!File.Exists(filepath))
            {
                // Create a file to write to.   
                using (StreamWriter sw = File.CreateText(filepath))
                {
                    sw.WriteLine(Message);
                }
            }
            else
            {
                using (StreamWriter sw = File.AppendText(filepath))
                {
                    sw.WriteLine(Message);
                }
            }
        }
    }
}
0

There are 0 best solutions below