Fetching Users On Windows System Using C#

This article discusses how to fetch User (Names/& Ids) who are registered and or logged on to Windows System including Windows Server. Please feel free to add and update as necessary, it is the wiki way!

Fetching All Users On The System

You can achieve this by using WQL to query Win32_UserAccount from your C# code as follows:

using System.Management // This namespace is required for SelectQuery Class and other management objects
 
SelectQuery query = new  SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new  ManagementObjectSearcher(query);
 
foreach(ManagementObject enVar in  searcher.Get())
{
    Console.WriteLine("UserName: {0}", enVar["Name"]);
}

Fetching All Logged On/Connected Users On Windows Server

You can achieve by using the following code:

using System.Runtime.InteropServices;        
 
        [DllImport("wtsapi32.dll")]
        static extern  IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] String pServerName);
 
        [DllImport("wtsapi32.dll")]
        static extern  void WTSCloseServer(IntPtr hServer);
 
        [DllImport("wtsapi32.dll")]
        static extern  Int32 WTSEnumerateSessions(
            IntPtr hServer,
            [MarshalAs(UnmanagedType.U4)] Int32 Reserved,
            [MarshalAs(UnmanagedType.U4)] Int32 Version,
            ref IntPtr ppSessionInfo,
            [MarshalAs(UnmanagedType.U4)] ref  Int32 pCount);
 
        [DllImport("wtsapi32.dll")]
        static extern  void WTSFreeMemory(IntPtr pMemory);
 
        [DllImport("Wtsapi32.dll")]
        static extern  bool WTSQuerySessionInformation(
            System.IntPtr hServer, int  sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint  pBytesReturned);
 
        [StructLayout(LayoutKind.Sequential)]
        private struct  WTS_SESSION_INFO
        {
            public Int32 SessionID;
 
            [MarshalAs(UnmanagedType.LPStr)]
            public String pWinStationName;
 
            public WTS_CONNECTSTATE_CLASS State;
        }
 
        public enum  WTS_INFO_CLASS
        {
            WTSInitialProgram,
            WTSApplicationName,
            WTSWorkingDirectory,
            WTSOEMId,
            WTSSessionId,
            WTSUserName,
            WTSWinStationName,
            WTSDomainName,
            WTSConnectState,
            WTSClientBuildNumber,
            WTSClientName,
            WTSClientDirectory,
            WTSClientProductId,
            WTSClientHardwareId,
            WTSClientAddress,
            WTSClientDisplay,
            WTSClientProtocolType
        }
        public enum  WTS_CONNECTSTATE_CLASS
        {
            WTSActive,
            WTSConnected,
            WTSConnectQuery,
            WTSShadow,
            WTSDisconnected,
            WTSIdle,
            WTSListen,
            WTSReset,
            WTSDown,
            WTSInit
        }
 
 
        public static  IntPtr OpenServer(String Name)
        {
            IntPtr server = WTSOpenServer(Name);
            return server;
        }
        public static  void CloseServer(IntPtr ServerHandle)
        {
            WTSCloseServer(ServerHandle);
        }
        public static  void ListUsers(String ServerName)
        {
            IntPtr serverHandle = IntPtr.Zero;
            List<String> resultList = new  List<string>();
            serverHandle = OpenServer(ServerName);
 
            try
            {
                IntPtr SessionInfoPtr = IntPtr.Zero;
                IntPtr userPtr = IntPtr.Zero;
                IntPtr domainPtr = IntPtr.Zero;
                Int32 sessionCount = 0;
                Int32 retVal = WTSEnumerateSessions(serverHandle, 0, 1, ref  SessionInfoPtr, ref  sessionCount);
                Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
                IntPtr currentSession = SessionInfoPtr;
                uint bytes = 0;
 
                if (retVal != 0)
                {
                    for (int i = 0; i < sessionCount; i++)
                    {
                        WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(WTS_SESSION_INFO));
                        currentSession += dataSize;
 
                        WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSUserName, out  userPtr, out  bytes);
                        WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSDomainName, out  domainPtr, out  bytes);
                                                                 // UserName and Domain is printed out here
                        Console.WriteLine("Domain and User: {0}\\{1}", Marshal.PtrToStringAnsi(domainPtr), Marshal.PtrToStringAnsi(userPtr));
 
                        WTSFreeMemory(userPtr);
                        WTSFreeMemory(domainPtr);
                    }
 
                    WTSFreeMemory(SessionInfoPtr);
                }
            }
            finally
            {
                CloseServer(serverHandle);
            }
        }

By calling the method ListUsers(String ServerName) you can display all the users with their corresponding Domain as well. And in case you want to display connected/Logged On users on the system where the assembly is executed then you can use the following code:

// Environment.MachineName shows the name of this System
ListUsers(Environment.MachineName.ToString());

References