Templates/Framework/Source/AppDeployToolkit/AppDeployToolkitMain.cs
// Date Modified: 03/27/2024
// Version Number:3.10.0 using System; using System.Text; using System.Collections; using System.ComponentModel; using System.DirectoryServices; using System.Security.Principal; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; namespace PSADT { public class Msi { enum LoadLibraryFlags : int { DONT_RESOLVE_DLL_REFERENCES = 0x00000001, LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, LOAD_LIBRARY_AS_DATAFILE = 0x00000002, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 } [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, LoadLibraryFlags dwFlags); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax); // Get MSI exit code message from msimsg.dll resource dll public static string GetMessageFromMsiExitCode(int errCode) { IntPtr hModuleInstance = LoadLibraryEx("msimsg.dll", IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE); StringBuilder sb = new StringBuilder(255); uint u = Convert.ToUInt32(errCode); LoadString(hModuleInstance, u, sb, sb.Capacity + 1); return sb.ToString(); } } public class Explorer { private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); private const int WM_SETTINGCHANGE = 0x1a; private const int SMTO_ABORTIFHUNG = 0x0002; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] static extern bool SendNotifyMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult); [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern void SHChangeNotify(int eventId, uint flags, IntPtr item1, IntPtr item2); public static void RefreshDesktopAndEnvironmentVariables() { // Update desktop icons SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero); SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero); // Update environment variables SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, "Environment", SMTO_ABORTIFHUNG, 100, IntPtr.Zero); } } public sealed class FileVerb { [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LoadString(IntPtr h, uint id, StringBuilder sb, int maxBuffer); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr LoadLibrary(string s); public static string GetPinVerb(int VerbId) { IntPtr hShell32 = LoadLibrary("shell32.dll"); const int nChars = 255; StringBuilder Buff = new StringBuilder("", nChars); uint u = Convert.ToUInt32(VerbId); LoadString(hShell32, u, Buff, Buff.Capacity); return Buff.ToString(); } } public sealed class IniFile { [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, StringBuilder lpString, string lpFileName); public static string GetIniValue(string section, string key, string filepath) { string sDefault = ""; const int nChars = 1024; StringBuilder Buff = new StringBuilder(nChars); GetPrivateProfileString(section, key, sDefault, Buff, Buff.Capacity, filepath); return Buff.ToString(); } public static void SetIniValue(string section, string key, StringBuilder value, string filepath) { WritePrivateProfileString(section, key, value, filepath); } } public class UiAutomation { public enum GetWindow_Cmd : int { GW_HWNDFIRST = 0, GW_HWNDLAST = 1, GW_HWNDNEXT = 2, GW_HWNDPREV = 3, GW_OWNER = 4, GW_CHILD = 5, GW_ENABLEDPOPUP = 6 } public enum ShowWindowEnum { Hide = 0, ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3, Maximize = 3, ShowNormalNoActivate = 4, Show = 5, Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8, Restore = 9, ShowDefault = 10, ForceMinimized = 11 } public enum UserNotificationState { // http://msdn.microsoft.com/en-us/library/bb762533(v=vs.85).aspx ScreenSaverOrLockedOrFastUserSwitching = 1, // A screen saver is displayed, the machine is locked, or a nonactive Fast User Switching session is in progress. FullScreenOrPresentationModeOrLoginScreen = 2, // A full-screen application is running or Presentation Settings are applied. Presentation Settings allow a user to put their machine into a state fit for an uninterrupted presentation, such as a set of PowerPoint slides, with a single click. Also returns this state if machine is at the login screen. RunningDirect3DFullScreen = 3, // A full-screen, exclusive mode, Direct3D application is running. PresentationMode = 4, // The user has activated Windows presentation settings to block notifications and pop-up messages. AcceptsNotifications = 5, // None of the other states are found, notifications can be freely sent. QuietTime = 6, // Introduced in Windows 7. The current user is in "quiet time", which is the first hour after a new user logs into his or her account for the first time. WindowsStoreAppRunning = 7 // Introduced in Windows 8. A Windows Store app is running. } // Only for Vista or above [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = false)] static extern int SHQueryUserNotificationState(out UserNotificationState pquns); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumWindows(EnumWindowsProcD lpEnumFunc, ref IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern IntPtr GetShellWindow(); public enum DeviceCap { HORZRES = 8, VERTRES = 10, DESKTOPVERTRES = 117, DESKTOPHORZRES = 118 } [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetDeviceCaps(IntPtr hDC, int nIndex); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWindowEnabled(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsIconic(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr SetActiveWindow(IntPtr hwnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr SetFocus(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern bool BringWindowToTop(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetCurrentThreadId(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern bool AttachThreadInput(int idAttach, int idAttachTo, bool fAttach); [DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr DestroyMenu(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern bool SetProcessDPIAware(); public delegate bool EnumWindowsProcD(IntPtr hWnd, ref IntPtr lItems); public static bool EnumWindowsProc(IntPtr hWnd, ref IntPtr lItems) { if (hWnd != IntPtr.Zero) { GCHandle hItems = GCHandle.FromIntPtr(lItems); List<IntPtr> items = hItems.Target as List<IntPtr>; items.Add(hWnd); return true; } else { return false; } } public static List<IntPtr> EnumWindows() { try { List<IntPtr> items = new List<IntPtr>(); EnumWindowsProcD CallBackPtr = new EnumWindowsProcD(EnumWindowsProc); GCHandle hItems = GCHandle.Alloc(items); IntPtr lItems = GCHandle.ToIntPtr(hItems); EnumWindows(CallBackPtr, ref lItems); return items; } catch (Exception ex) { throw new Exception("An error occured during window enumeration: " + ex.Message); } } public static string GetWindowText(IntPtr hWnd) { int iTextLength = GetWindowTextLength(hWnd); if (iTextLength > 0) { StringBuilder sb = new StringBuilder(iTextLength); GetWindowText(hWnd, sb, iTextLength + 1); return sb.ToString(); } else { return String.Empty; } } public static bool BringWindowToFront(IntPtr windowHandle) { bool breturn = false; if (IsIconic(windowHandle)) { // Show minimized window because SetForegroundWindow does not work for minimized windows ShowWindow(windowHandle, ShowWindowEnum.ShowMaximized); } int lpdwProcessId; int windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(), out lpdwProcessId); int currentThreadId = GetCurrentThreadId(); AttachThreadInput(windowThreadProcessId, currentThreadId, true); BringWindowToTop(windowHandle); breturn = SetForegroundWindow(windowHandle); SetActiveWindow(windowHandle); SetFocus(windowHandle); AttachThreadInput(windowThreadProcessId, currentThreadId, false); return breturn; } public static int GetWindowThreadProcessId(IntPtr windowHandle) { int processID = 0; GetWindowThreadProcessId(windowHandle, out processID); return processID; } public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex) { if (IntPtr.Size == 4) { return GetWindowLong32(hWnd, nIndex); } return GetWindowLongPtr64(hWnd, nIndex); } public static string GetUserNotificationState() { // Only works for Windows Vista or higher UserNotificationState state; int returnVal = SHQueryUserNotificationState(out state); return state.ToString(); } } public class QueryUser { [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern IntPtr WTSOpenServer(string pServerName); [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern void WTSCloseServer(IntPtr hServer); [DllImport("wtsapi32.dll", CharSet = CharSet.Ansi, SetLastError = false)] public static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out IntPtr pBuffer, out int pBytesReturned); [DllImport("wtsapi32.dll", CharSet = CharSet.Ansi, SetLastError = false)] public static extern int WTSEnumerateSessions(IntPtr hServer, int Reserved, int Version, out IntPtr pSessionInfo, out int pCount); [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern void WTSFreeMemory(IntPtr pMemory); [DllImport("winsta.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int WinStationQueryInformation(IntPtr hServer, int sessionId, int information, ref WINSTATIONINFORMATIONW pBuffer, int bufferLength, ref int returnedLength); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern int GetCurrentProcessId(); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = false)] public static extern bool ProcessIdToSessionId(int processId, ref int pSessionId); public class TerminalSessionData { public int SessionId; public string ConnectionState; public string SessionName; public bool IsUserSession; public TerminalSessionData(int sessionId, string connState, string sessionName, bool isUserSession) { SessionId = sessionId; ConnectionState = connState; SessionName = sessionName; IsUserSession = isUserSession; } } public class TerminalSessionInfo { public string NTAccount; public string SID; public string UserName; public string DomainName; public int SessionId; public string SessionName; public string ConnectState; public bool IsCurrentSession; public bool IsConsoleSession; public bool IsActiveUserSession; public bool IsUserSession; public bool IsRdpSession; public bool IsLocalAdmin; public DateTime? LogonTime; public TimeSpan? IdleTime; public DateTime? DisconnectTime; public string ClientName; public string ClientProtocolType; public string ClientDirectory; public int ClientBuildNumber; } [StructLayout(LayoutKind.Sequential)] private struct WTS_SESSION_INFO { public Int32 SessionId; [MarshalAs(UnmanagedType.LPStr)] public string SessionName; public WTS_CONNECTSTATE_CLASS State; } [StructLayout(LayoutKind.Sequential)] public struct WINSTATIONINFORMATIONW { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 70)] private byte[] Reserved1; public int SessionId; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] private byte[] Reserved2; public FILETIME ConnectTime; public FILETIME DisconnectTime; public FILETIME LastInputTime; public FILETIME LoginTime; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1096)] private byte[] Reserved3; public FILETIME CurrentTime; } public enum WINSTATIONINFOCLASS { WinStationInformation = 8 } public enum WTS_CONNECTSTATE_CLASS { Active, Connected, ConnectQuery, Shadow, Disconnected, Idle, Listen, Reset, Down, Init } public enum WTS_INFO_CLASS { SessionId = 4, UserName, SessionName, DomainName, ConnectState, ClientBuildNumber, ClientName, ClientDirectory, ClientProtocolType = 16 } private static IntPtr OpenServer(string Name) { IntPtr server = WTSOpenServer(Name); return server; } private static void CloseServer(IntPtr ServerHandle) { WTSCloseServer(ServerHandle); } private static IList<T> PtrToStructureList<T>(IntPtr ppList, int count) where T : struct { List<T> result = new List<T>(); long pointer = ppList.ToInt64(); int sizeOf = Marshal.SizeOf(typeof(T)); for (int index = 0; index < count; index++) { T item = (T)Marshal.PtrToStructure(new IntPtr(pointer), typeof(T)); result.Add(item); pointer += sizeOf; } return result; } public static DateTime? FileTimeToDateTime(FILETIME ft) { if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0) { return null; } long hFT = (((long)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; return DateTime.FromFileTime(hFT); } public static WINSTATIONINFORMATIONW GetWinStationInformation(IntPtr server, int sessionId) { int retLen = 0; WINSTATIONINFORMATIONW wsInfo = new WINSTATIONINFORMATIONW(); WinStationQueryInformation(server, sessionId, (int)WINSTATIONINFOCLASS.WinStationInformation, ref wsInfo, Marshal.SizeOf(typeof(WINSTATIONINFORMATIONW)), ref retLen); return wsInfo; } public static TerminalSessionData[] ListSessions(string ServerName) { IntPtr server = IntPtr.Zero; if (ServerName == "localhost" || ServerName == String.Empty) { ServerName = Environment.MachineName; } List<TerminalSessionData> results = new List<TerminalSessionData>(); try { server = OpenServer(ServerName); IntPtr ppSessionInfo = IntPtr.Zero; int count; bool _isUserSession = false; IList<WTS_SESSION_INFO> sessionsInfo; if (WTSEnumerateSessions(server, 0, 1, out ppSessionInfo, out count) == 0) { throw new Win32Exception(); } try { sessionsInfo = PtrToStructureList<WTS_SESSION_INFO>(ppSessionInfo, count); } finally { WTSFreeMemory(ppSessionInfo); } foreach (WTS_SESSION_INFO sessionInfo in sessionsInfo) { if (sessionInfo.SessionName != "Services" && sessionInfo.SessionName != "RDP-Tcp") { _isUserSession = true; } results.Add(new TerminalSessionData(sessionInfo.SessionId, sessionInfo.State.ToString(), sessionInfo.SessionName, _isUserSession)); _isUserSession = false; } } finally { CloseServer(server); } TerminalSessionData[] returnData = results.ToArray(); return returnData; } public static TerminalSessionInfo GetSessionInfo(string ServerName, int SessionId) { IntPtr server = IntPtr.Zero; IntPtr buffer = IntPtr.Zero; int bytesReturned; TerminalSessionInfo data = new TerminalSessionInfo(); bool _IsCurrentSessionId = false; bool _IsConsoleSession = false; bool _IsUserSession = false; int currentSessionID = 0; string _NTAccount = String.Empty; if (ServerName == "localhost" || ServerName == String.Empty) { ServerName = Environment.MachineName; } if (ProcessIdToSessionId(GetCurrentProcessId(), ref currentSessionID) == false) { currentSessionID = -1; } // Get all members of the local administrators group bool _IsLocalAdminCheckSuccess = false; List<string> localAdminGroupSidsList = new List<string>(); try { DirectoryEntry localMachine = new DirectoryEntry("WinNT://" + ServerName + ",Computer"); string localAdminGroupName = new SecurityIdentifier("S-1-5-32-544").Translate(typeof(NTAccount)).Value.Split('\\')[1]; DirectoryEntry admGroup = localMachine.Children.Find(localAdminGroupName, "group"); object members = admGroup.Invoke("members", null); string validSidPattern = @"^S-\d-\d+-(\d+-){1,14}\d+$"; foreach (object groupMember in (IEnumerable)members) { DirectoryEntry member = new DirectoryEntry(groupMember); if (member.Name != String.Empty) { if (Regex.IsMatch(member.Name, validSidPattern)) { localAdminGroupSidsList.Add(member.Name); } else { localAdminGroupSidsList.Add((new NTAccount(member.Name)).Translate(typeof(SecurityIdentifier)).Value); } } } _IsLocalAdminCheckSuccess = true; } catch { } try { server = OpenServer(ServerName); if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.ClientBuildNumber, out buffer, out bytesReturned) == false) { return data; } int lData = Marshal.ReadInt32(buffer); data.ClientBuildNumber = lData; if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.ClientDirectory, out buffer, out bytesReturned) == false) { return data; } string strData = Marshal.PtrToStringAnsi(buffer); data.ClientDirectory = strData; if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.ClientName, out buffer, out bytesReturned) == false) { return data; } strData = Marshal.PtrToStringAnsi(buffer); data.ClientName = strData; if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.ClientProtocolType, out buffer, out bytesReturned) == false) { return data; } Int16 intData = Marshal.ReadInt16(buffer); if (intData == 2) { strData = "RDP"; data.IsRdpSession = true; } else { strData = ""; data.IsRdpSession = false; } data.ClientProtocolType = strData; if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.ConnectState, out buffer, out bytesReturned) == false) { return data; } lData = Marshal.ReadInt32(buffer); data.ConnectState = ((WTS_CONNECTSTATE_CLASS)lData).ToString(); if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.SessionId, out buffer, out bytesReturned) == false) { return data; } lData = Marshal.ReadInt32(buffer); data.SessionId = lData; if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.DomainName, out buffer, out bytesReturned) == false) { return data; } strData = Marshal.PtrToStringAnsi(buffer).ToUpper(); data.DomainName = strData; if (strData != String.Empty) { _NTAccount = strData; } if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.UserName, out buffer, out bytesReturned) == false) { return data; } strData = Marshal.PtrToStringAnsi(buffer); data.UserName = strData; if (strData != String.Empty) { data.NTAccount = _NTAccount + "\\" + strData; string _Sid = (new NTAccount(_NTAccount + "\\" + strData)).Translate(typeof(SecurityIdentifier)).Value; data.SID = _Sid; if (_IsLocalAdminCheckSuccess == true) { foreach (string localAdminGroupSid in localAdminGroupSidsList) { if (localAdminGroupSid == _Sid) { data.IsLocalAdmin = true; break; } else { data.IsLocalAdmin = false; } } } } if (WTSQuerySessionInformation(server, SessionId, WTS_INFO_CLASS.SessionName, out buffer, out bytesReturned) == false) { return data; } strData = Marshal.PtrToStringAnsi(buffer); data.SessionName = strData; if (strData != "Services" && strData != "RDP-Tcp" && data.UserName != String.Empty) { _IsUserSession = true; } data.IsUserSession = _IsUserSession; if (strData == "Console") { _IsConsoleSession = true; } data.IsConsoleSession = _IsConsoleSession; WINSTATIONINFORMATIONW wsInfo = GetWinStationInformation(server, SessionId); DateTime? _loginTime = FileTimeToDateTime(wsInfo.LoginTime); DateTime? _lastInputTime = FileTimeToDateTime(wsInfo.LastInputTime); DateTime? _disconnectTime = FileTimeToDateTime(wsInfo.DisconnectTime); DateTime? _currentTime = FileTimeToDateTime(wsInfo.CurrentTime); TimeSpan? _idleTime = (_currentTime != null && _lastInputTime != null) ? _currentTime.Value - _lastInputTime.Value : TimeSpan.Zero; data.LogonTime = _loginTime; data.IdleTime = _idleTime; data.DisconnectTime = _disconnectTime; if (currentSessionID == SessionId) { _IsCurrentSessionId = true; } data.IsCurrentSession = _IsCurrentSessionId; } finally { WTSFreeMemory(buffer); buffer = IntPtr.Zero; CloseServer(server); } return data; } public static TerminalSessionInfo[] GetUserSessionInfo(string ServerName) { if (ServerName == "localhost" || ServerName == String.Empty) { ServerName = Environment.MachineName; } // Find and get detailed information for all user sessions // Also determine the active user session. If a console user exists, then that will be the active user session. // If no console user exists but users are logged in, such as on terminal servers, then select the first logged-in non-console user that is either 'Active' or 'Connected' as the active user. TerminalSessionData[] sessions = ListSessions(ServerName); TerminalSessionInfo sessionInfo = new TerminalSessionInfo(); List<TerminalSessionInfo> userSessionsInfo = new List<TerminalSessionInfo>(); string firstActiveUserNTAccount = String.Empty; bool IsActiveUserSessionSet = false; foreach (TerminalSessionData session in sessions) { if (session.IsUserSession == true) { sessionInfo = GetSessionInfo(ServerName, session.SessionId); if (sessionInfo.IsUserSession == true) { if ((firstActiveUserNTAccount == String.Empty) && (sessionInfo.ConnectState == "Active" || sessionInfo.ConnectState == "Connected")) { firstActiveUserNTAccount = sessionInfo.NTAccount; } if (sessionInfo.IsConsoleSession == true) { sessionInfo.IsActiveUserSession = true; IsActiveUserSessionSet = true; } else { sessionInfo.IsActiveUserSession = false; } userSessionsInfo.Add(sessionInfo); } } } TerminalSessionInfo[] userSessions = userSessionsInfo.ToArray(); if (IsActiveUserSessionSet == false) { foreach (TerminalSessionInfo userSession in userSessions) { if (userSession.NTAccount == firstActiveUserNTAccount) { userSession.IsActiveUserSession = true; break; } } } return userSessions; } } } |