build employee Monitoring service tool. I use windows service to build the tool. Now iam very confused which service account i need to use to build this tool. This confusion occurs when I tried to log system lock and unlock time using localsytem account .The event is not triggered . After some time of debugging i understand local system is running on service 0 session it's does not have access desktop settings . I need to give full access company employer . In future the features will be enhanced ,like app use by employee , track network, shut down and open etc . Can anyone help me
I tried on service start subscribing, session switch . It subscribing successfully. But the event is not triggering.
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading;
namespace MyFirstService
{
public partial class Service1 : ServiceBase
{
private Thread pipeServerThread;
private bool isRunning = true;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WriteToFile("Service started at " + DateTime.Now);
// Start Named Pipe Server
pipeServerThread = new Thread(StartNamedPipeServer);
pipeServerThread.IsBackground = true;
pipeServerThread.Start();
// Start the helper process in user session
StartUserSessionMonitor();
}
protected override void OnStop()
{
WriteToFile("Service stopped at " + DateTime.Now);
isRunning = false;
}
private void StartNamedPipeServer()
{
while (isRunning)
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("SessionPipe", PipeDirection.In))
{
WriteToFile("Waiting for connection...");
pipeServer.WaitForConnection();
using (StreamReader reader = new StreamReader(pipeServer))
{
string message = reader.ReadLine();
if (!string.IsNullOrEmpty(message))
{
WriteToFile("Received: " + message);
}
}
}
}
}
private void StartUserSessionMonitor()
{
try
{
string exePath = @"C:\Users\DELL\source\repos\HelperApp\bin\Debug\net8.0-windows\HelperApp.exe";
uint sessionId = WTSGetActiveConsoleSessionId();
if (sessionId == 0xFFFFFFFF)
{
WriteToFile("No active console session found.");
return;
}
if (!WTSQueryUserToken(sessionId, out IntPtr userToken))
{
WriteToFile($"Failed to retrieve user token for session {sessionId}. Error: {Marshal.GetLastWin32Error()}");
return;
}
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
if (!DuplicateTokenEx(userToken, 0xF01FF, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, out IntPtr duplicatedToken))
{
WriteToFile($"Failed to duplicate token. Error: {Marshal.GetLastWin32Error()}");
CloseHandle(userToken);
return;
}
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "winsta0\\default";
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
string commandLine = $"\"{exePath}\"";
if (!CreateProcessAsUser(duplicatedToken, null, commandLine, ref sa, ref sa, false, 0, IntPtr.Zero, null, ref si, ref pi))
{
WriteToFile($"Failed to create process. Error: {Marshal.GetLastWin32Error()}");
}
else
{
WriteToFile($"Successfully launched process in session {sessionId} with PID {pi.dwProcessId}.");
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(duplicatedToken);
CloseHandle(userToken);
}
catch (Exception ex)
{
WriteToFile("Failed to start user session monitor: " + ex.Message);
}
}
public void WriteToFile(string Message)
{
try
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath = Path.Combine(path, "ServiceLog_" + DateTime.Now.Date.ToShortDateString().Replace('/', '_') + ".txt");
using (StreamWriter sw = File.AppendText(filepath))
{
sw.WriteLine($"{DateTime.Now}: {Message}");
}
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", $"Failed to write to log file: {ex.Message}", EventLogEntryType.Error);
}
}
#region P/Invoke Declarations
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint WTSGetActiveConsoleSessionId();
[DllImport("wtsapi32.dll", SetLastError = true)]
private static extern bool WTSQueryUserToken(uint sessionId, out IntPtr phToken);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpTokenAttributes, int ImpersonationLevel, int TokenType, out IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, ref PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_ATTRIBUTES
{
public int Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
private enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
private enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
#endregion
}
}