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