How do you retrieve a list of logged-in/connected users in .NET?












24














Here's the scenario:



You have a Windows server that users remotely connect to via RDP. You want your program (which runs as a service) to know who is currently connected. This may or may not include an interactive console session.



Please note that this is the not the same as just retrieving the current interactive user.



I'm guessing that there is some sort of API access to Terminal Services to get this info?










share|improve this question





























    24














    Here's the scenario:



    You have a Windows server that users remotely connect to via RDP. You want your program (which runs as a service) to know who is currently connected. This may or may not include an interactive console session.



    Please note that this is the not the same as just retrieving the current interactive user.



    I'm guessing that there is some sort of API access to Terminal Services to get this info?










    share|improve this question



























      24












      24








      24


      12





      Here's the scenario:



      You have a Windows server that users remotely connect to via RDP. You want your program (which runs as a service) to know who is currently connected. This may or may not include an interactive console session.



      Please note that this is the not the same as just retrieving the current interactive user.



      I'm guessing that there is some sort of API access to Terminal Services to get this info?










      share|improve this question















      Here's the scenario:



      You have a Windows server that users remotely connect to via RDP. You want your program (which runs as a service) to know who is currently connected. This may or may not include an interactive console session.



      Please note that this is the not the same as just retrieving the current interactive user.



      I'm guessing that there is some sort of API access to Terminal Services to get this info?







      c# .net windows-services login






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 28 '10 at 20:59









      John Saunders

      147k22204360




      147k22204360










      asked Sep 25 '08 at 11:02









      James

      1,10211731




      1,10211731
























          4 Answers
          4






          active

          oldest

          votes


















          28














          Here's my take on the issue:



          using System;
          using System.Collections.Generic;
          using System.Text;
          using System.Runtime.InteropServices;

          namespace EnumerateRDUsers
          {
          class Program
          {
          [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
          }

          static void Main(string args)
          {
          ListUsers(Environment.MachineName);
          }

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

          Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\" + Marshal.PtrToStringAnsi(userPtr));

          WTSFreeMemory(userPtr);
          WTSFreeMemory(domainPtr);
          }

          WTSFreeMemory(SessionInfoPtr);
          }
          }
          finally
          {
          CloseServer(serverHandle);
          }

          }

          }
          }





          share|improve this answer



















          • 12




            I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
            – Scott Chamberlain
            Apr 20 '10 at 21:49






          • 1




            Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
            – M_Mogharrabi
            Jan 22 '13 at 6:31










          • @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
            – Magnus Johansson
            Jan 22 '13 at 10:03










          • @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
            – M_Mogharrabi
            Jan 26 '13 at 7:07






          • 4




            Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
            – noggin182
            Jan 26 '17 at 14:25



















          19














          Another option, if you don't want to deal with the P/Invokes yourself, would be to use the Cassia library:



          using System;
          using System.Security.Principal;
          using Cassia;

          namespace CassiaSample
          {
          public static class Program
          {
          public static void Main(string args)
          {
          ITerminalServicesManager manager = new TerminalServicesManager();
          using (ITerminalServer server = manager.GetRemoteServer("your-server-name"))
          {
          server.Open();
          foreach (ITerminalServicesSession session in server.GetSessions())
          {
          NTAccount account = session.UserAccount;
          if (account != null)
          {
          Console.WriteLine(account);
          }
          }
          }
          }
          }
          }





          share|improve this answer

















          • 1




            That looks really easy to use. Thanks for adding that.
            – James
            May 15 '09 at 8:38










          • Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
            – DaddioNTS
            Aug 11 '17 at 12:58



















          5














          Ok, one solution to my own question.



          You can use WMI to retreive a list of running processes. You can also look at the owners of these processes. If you look at the owners of "explorer.exe" (and remove the duplicates) you should end up with a list of logged in users.






          share|improve this answer





























            1














            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.Runtime.InteropServices;

            namespace TerminalServices
            {
            class TSManager
            {
            [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);

            [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_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 List<String> ListSessions(String ServerName)
            {
            IntPtr server = IntPtr.Zero;
            List<String> ret = new List<string>();
            server = OpenServer(ServerName);

            try
            {
            IntPtr ppSessionInfo = IntPtr.Zero;

            Int32 count = 0;
            Int32 retval = WTSEnumerateSessions(server, 0, 1, ref ppSessionInfo, ref count);
            Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

            Int32 current = (int)ppSessionInfo;

            if (retval != 0)
            {
            for (int i = 0; i < count; i++)
            {
            WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
            current += dataSize;

            ret.Add(si.SessionID + " " + si.State + " " + si.pWinStationName);
            }

            WTSFreeMemory(ppSessionInfo);
            }
            }
            finally
            {
            CloseServer(server);
            }

            return ret;
            }
            }
            }





            share|improve this answer





















            • This gives you some usefulinfo but not the usernames.
              – James
              Sep 25 '08 at 11:40










            • How are we calling it?
              – Si8
              Apr 4 '17 at 15:30











            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f132620%2fhow-do-you-retrieve-a-list-of-logged-in-connected-users-in-net%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            4 Answers
            4






            active

            oldest

            votes








            4 Answers
            4






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            28














            Here's my take on the issue:



            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.Runtime.InteropServices;

            namespace EnumerateRDUsers
            {
            class Program
            {
            [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
            }

            static void Main(string args)
            {
            ListUsers(Environment.MachineName);
            }

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

            Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\" + Marshal.PtrToStringAnsi(userPtr));

            WTSFreeMemory(userPtr);
            WTSFreeMemory(domainPtr);
            }

            WTSFreeMemory(SessionInfoPtr);
            }
            }
            finally
            {
            CloseServer(serverHandle);
            }

            }

            }
            }





            share|improve this answer



















            • 12




              I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
              – Scott Chamberlain
              Apr 20 '10 at 21:49






            • 1




              Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
              – M_Mogharrabi
              Jan 22 '13 at 6:31










            • @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
              – Magnus Johansson
              Jan 22 '13 at 10:03










            • @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
              – M_Mogharrabi
              Jan 26 '13 at 7:07






            • 4




              Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
              – noggin182
              Jan 26 '17 at 14:25
















            28














            Here's my take on the issue:



            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.Runtime.InteropServices;

            namespace EnumerateRDUsers
            {
            class Program
            {
            [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
            }

            static void Main(string args)
            {
            ListUsers(Environment.MachineName);
            }

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

            Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\" + Marshal.PtrToStringAnsi(userPtr));

            WTSFreeMemory(userPtr);
            WTSFreeMemory(domainPtr);
            }

            WTSFreeMemory(SessionInfoPtr);
            }
            }
            finally
            {
            CloseServer(serverHandle);
            }

            }

            }
            }





            share|improve this answer



















            • 12




              I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
              – Scott Chamberlain
              Apr 20 '10 at 21:49






            • 1




              Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
              – M_Mogharrabi
              Jan 22 '13 at 6:31










            • @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
              – Magnus Johansson
              Jan 22 '13 at 10:03










            • @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
              – M_Mogharrabi
              Jan 26 '13 at 7:07






            • 4




              Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
              – noggin182
              Jan 26 '17 at 14:25














            28












            28








            28






            Here's my take on the issue:



            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.Runtime.InteropServices;

            namespace EnumerateRDUsers
            {
            class Program
            {
            [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
            }

            static void Main(string args)
            {
            ListUsers(Environment.MachineName);
            }

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

            Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\" + Marshal.PtrToStringAnsi(userPtr));

            WTSFreeMemory(userPtr);
            WTSFreeMemory(domainPtr);
            }

            WTSFreeMemory(SessionInfoPtr);
            }
            }
            finally
            {
            CloseServer(serverHandle);
            }

            }

            }
            }





            share|improve this answer














            Here's my take on the issue:



            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.Runtime.InteropServices;

            namespace EnumerateRDUsers
            {
            class Program
            {
            [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
            }

            static void Main(string args)
            {
            ListUsers(Environment.MachineName);
            }

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

            Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\" + Marshal.PtrToStringAnsi(userPtr));

            WTSFreeMemory(userPtr);
            WTSFreeMemory(domainPtr);
            }

            WTSFreeMemory(SessionInfoPtr);
            }
            }
            finally
            {
            CloseServer(serverHandle);
            }

            }

            }
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Aug 8 at 0:37









            M.R.T2017

            194212




            194212










            answered Sep 25 '08 at 11:42









            Magnus Johansson

            21.2k1585140




            21.2k1585140








            • 12




              I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
              – Scott Chamberlain
              Apr 20 '10 at 21:49






            • 1




              Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
              – M_Mogharrabi
              Jan 22 '13 at 6:31










            • @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
              – Magnus Johansson
              Jan 22 '13 at 10:03










            • @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
              – M_Mogharrabi
              Jan 26 '13 at 7:07






            • 4




              Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
              – noggin182
              Jan 26 '17 at 14:25














            • 12




              I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
              – Scott Chamberlain
              Apr 20 '10 at 21:49






            • 1




              Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
              – M_Mogharrabi
              Jan 22 '13 at 6:31










            • @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
              – Magnus Johansson
              Jan 22 '13 at 10:03










            • @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
              – M_Mogharrabi
              Jan 26 '13 at 7:07






            • 4




              Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
              – noggin182
              Jan 26 '17 at 14:25








            12




            12




            I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
            – Scott Chamberlain
            Apr 20 '10 at 21:49




            I know this is a bit of thread necomancy but if anyone uses this there is a memory leek. add WTSFreeMemory(userPtr); WTSFreeMemory(domainPtr); after the Console.Writeline to fix it.
            – Scott Chamberlain
            Apr 20 '10 at 21:49




            1




            1




            Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
            – M_Mogharrabi
            Jan 22 '13 at 6:31




            Hi Magnus,I tried your code, but it just returned the logged in user to the current client system in my local LAN.Is there any way to get all logged in users with systems client name in a local LAN with the above code?
            – M_Mogharrabi
            Jan 22 '13 at 6:31












            @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
            – Magnus Johansson
            Jan 22 '13 at 10:03




            @M_Mogharrabi , sorry your question doesn't really make sense to me. This code is meant to be run on a server, I don't know what you mean by "current client system" Can you please re-phrase?
            – Magnus Johansson
            Jan 22 '13 at 10:03












            @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
            – M_Mogharrabi
            Jan 26 '13 at 7:07




            @Magnus,Thanks for your reply,I want to get list of users who are logged in right now in a local network and i thought your code can do this(I did not know it should run on a server).So i tried on a client system but it just returned the user who had log in on that client system.
            – M_Mogharrabi
            Jan 26 '13 at 7:07




            4




            4




            Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
            – noggin182
            Jan 26 '17 at 14:25




            Tried to make an edit to fix an important bug here, but it got rejected :/ The type of currentSession should be IntPtr and not Int32. Running this code on 64bit systems will result in an overflow exception if the pointer address exceeds the Int32.MaxValue.
            – noggin182
            Jan 26 '17 at 14:25













            19














            Another option, if you don't want to deal with the P/Invokes yourself, would be to use the Cassia library:



            using System;
            using System.Security.Principal;
            using Cassia;

            namespace CassiaSample
            {
            public static class Program
            {
            public static void Main(string args)
            {
            ITerminalServicesManager manager = new TerminalServicesManager();
            using (ITerminalServer server = manager.GetRemoteServer("your-server-name"))
            {
            server.Open();
            foreach (ITerminalServicesSession session in server.GetSessions())
            {
            NTAccount account = session.UserAccount;
            if (account != null)
            {
            Console.WriteLine(account);
            }
            }
            }
            }
            }
            }





            share|improve this answer

















            • 1




              That looks really easy to use. Thanks for adding that.
              – James
              May 15 '09 at 8:38










            • Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
              – DaddioNTS
              Aug 11 '17 at 12:58
















            19














            Another option, if you don't want to deal with the P/Invokes yourself, would be to use the Cassia library:



            using System;
            using System.Security.Principal;
            using Cassia;

            namespace CassiaSample
            {
            public static class Program
            {
            public static void Main(string args)
            {
            ITerminalServicesManager manager = new TerminalServicesManager();
            using (ITerminalServer server = manager.GetRemoteServer("your-server-name"))
            {
            server.Open();
            foreach (ITerminalServicesSession session in server.GetSessions())
            {
            NTAccount account = session.UserAccount;
            if (account != null)
            {
            Console.WriteLine(account);
            }
            }
            }
            }
            }
            }





            share|improve this answer

















            • 1




              That looks really easy to use. Thanks for adding that.
              – James
              May 15 '09 at 8:38










            • Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
              – DaddioNTS
              Aug 11 '17 at 12:58














            19












            19








            19






            Another option, if you don't want to deal with the P/Invokes yourself, would be to use the Cassia library:



            using System;
            using System.Security.Principal;
            using Cassia;

            namespace CassiaSample
            {
            public static class Program
            {
            public static void Main(string args)
            {
            ITerminalServicesManager manager = new TerminalServicesManager();
            using (ITerminalServer server = manager.GetRemoteServer("your-server-name"))
            {
            server.Open();
            foreach (ITerminalServicesSession session in server.GetSessions())
            {
            NTAccount account = session.UserAccount;
            if (account != null)
            {
            Console.WriteLine(account);
            }
            }
            }
            }
            }
            }





            share|improve this answer












            Another option, if you don't want to deal with the P/Invokes yourself, would be to use the Cassia library:



            using System;
            using System.Security.Principal;
            using Cassia;

            namespace CassiaSample
            {
            public static class Program
            {
            public static void Main(string args)
            {
            ITerminalServicesManager manager = new TerminalServicesManager();
            using (ITerminalServer server = manager.GetRemoteServer("your-server-name"))
            {
            server.Open();
            foreach (ITerminalServicesSession session in server.GetSessions())
            {
            NTAccount account = session.UserAccount;
            if (account != null)
            {
            Console.WriteLine(account);
            }
            }
            }
            }
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered May 1 '09 at 1:56









            Dan Ports

            1,30187




            1,30187








            • 1




              That looks really easy to use. Thanks for adding that.
              – James
              May 15 '09 at 8:38










            • Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
              – DaddioNTS
              Aug 11 '17 at 12:58














            • 1




              That looks really easy to use. Thanks for adding that.
              – James
              May 15 '09 at 8:38










            • Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
              – DaddioNTS
              Aug 11 '17 at 12:58








            1




            1




            That looks really easy to use. Thanks for adding that.
            – James
            May 15 '09 at 8:38




            That looks really easy to use. Thanks for adding that.
            – James
            May 15 '09 at 8:38












            Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
            – DaddioNTS
            Aug 11 '17 at 12:58




            Cassia is great except you can't get the Source Network Address only the Client IP address which will be their internal network address if they are behind a router.
            – DaddioNTS
            Aug 11 '17 at 12:58











            5














            Ok, one solution to my own question.



            You can use WMI to retreive a list of running processes. You can also look at the owners of these processes. If you look at the owners of "explorer.exe" (and remove the duplicates) you should end up with a list of logged in users.






            share|improve this answer


























              5














              Ok, one solution to my own question.



              You can use WMI to retreive a list of running processes. You can also look at the owners of these processes. If you look at the owners of "explorer.exe" (and remove the duplicates) you should end up with a list of logged in users.






              share|improve this answer
























                5












                5








                5






                Ok, one solution to my own question.



                You can use WMI to retreive a list of running processes. You can also look at the owners of these processes. If you look at the owners of "explorer.exe" (and remove the duplicates) you should end up with a list of logged in users.






                share|improve this answer












                Ok, one solution to my own question.



                You can use WMI to retreive a list of running processes. You can also look at the owners of these processes. If you look at the owners of "explorer.exe" (and remove the duplicates) you should end up with a list of logged in users.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 25 '08 at 11:17









                James

                1,10211731




                1,10211731























                    1














                    using System;
                    using System.Collections.Generic;
                    using System.Text;
                    using System.Runtime.InteropServices;

                    namespace TerminalServices
                    {
                    class TSManager
                    {
                    [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);

                    [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_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 List<String> ListSessions(String ServerName)
                    {
                    IntPtr server = IntPtr.Zero;
                    List<String> ret = new List<string>();
                    server = OpenServer(ServerName);

                    try
                    {
                    IntPtr ppSessionInfo = IntPtr.Zero;

                    Int32 count = 0;
                    Int32 retval = WTSEnumerateSessions(server, 0, 1, ref ppSessionInfo, ref count);
                    Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

                    Int32 current = (int)ppSessionInfo;

                    if (retval != 0)
                    {
                    for (int i = 0; i < count; i++)
                    {
                    WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
                    current += dataSize;

                    ret.Add(si.SessionID + " " + si.State + " " + si.pWinStationName);
                    }

                    WTSFreeMemory(ppSessionInfo);
                    }
                    }
                    finally
                    {
                    CloseServer(server);
                    }

                    return ret;
                    }
                    }
                    }





                    share|improve this answer





















                    • This gives you some usefulinfo but not the usernames.
                      – James
                      Sep 25 '08 at 11:40










                    • How are we calling it?
                      – Si8
                      Apr 4 '17 at 15:30
















                    1














                    using System;
                    using System.Collections.Generic;
                    using System.Text;
                    using System.Runtime.InteropServices;

                    namespace TerminalServices
                    {
                    class TSManager
                    {
                    [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);

                    [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_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 List<String> ListSessions(String ServerName)
                    {
                    IntPtr server = IntPtr.Zero;
                    List<String> ret = new List<string>();
                    server = OpenServer(ServerName);

                    try
                    {
                    IntPtr ppSessionInfo = IntPtr.Zero;

                    Int32 count = 0;
                    Int32 retval = WTSEnumerateSessions(server, 0, 1, ref ppSessionInfo, ref count);
                    Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

                    Int32 current = (int)ppSessionInfo;

                    if (retval != 0)
                    {
                    for (int i = 0; i < count; i++)
                    {
                    WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
                    current += dataSize;

                    ret.Add(si.SessionID + " " + si.State + " " + si.pWinStationName);
                    }

                    WTSFreeMemory(ppSessionInfo);
                    }
                    }
                    finally
                    {
                    CloseServer(server);
                    }

                    return ret;
                    }
                    }
                    }





                    share|improve this answer





















                    • This gives you some usefulinfo but not the usernames.
                      – James
                      Sep 25 '08 at 11:40










                    • How are we calling it?
                      – Si8
                      Apr 4 '17 at 15:30














                    1












                    1








                    1






                    using System;
                    using System.Collections.Generic;
                    using System.Text;
                    using System.Runtime.InteropServices;

                    namespace TerminalServices
                    {
                    class TSManager
                    {
                    [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);

                    [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_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 List<String> ListSessions(String ServerName)
                    {
                    IntPtr server = IntPtr.Zero;
                    List<String> ret = new List<string>();
                    server = OpenServer(ServerName);

                    try
                    {
                    IntPtr ppSessionInfo = IntPtr.Zero;

                    Int32 count = 0;
                    Int32 retval = WTSEnumerateSessions(server, 0, 1, ref ppSessionInfo, ref count);
                    Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

                    Int32 current = (int)ppSessionInfo;

                    if (retval != 0)
                    {
                    for (int i = 0; i < count; i++)
                    {
                    WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
                    current += dataSize;

                    ret.Add(si.SessionID + " " + si.State + " " + si.pWinStationName);
                    }

                    WTSFreeMemory(ppSessionInfo);
                    }
                    }
                    finally
                    {
                    CloseServer(server);
                    }

                    return ret;
                    }
                    }
                    }





                    share|improve this answer












                    using System;
                    using System.Collections.Generic;
                    using System.Text;
                    using System.Runtime.InteropServices;

                    namespace TerminalServices
                    {
                    class TSManager
                    {
                    [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);

                    [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_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 List<String> ListSessions(String ServerName)
                    {
                    IntPtr server = IntPtr.Zero;
                    List<String> ret = new List<string>();
                    server = OpenServer(ServerName);

                    try
                    {
                    IntPtr ppSessionInfo = IntPtr.Zero;

                    Int32 count = 0;
                    Int32 retval = WTSEnumerateSessions(server, 0, 1, ref ppSessionInfo, ref count);
                    Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

                    Int32 current = (int)ppSessionInfo;

                    if (retval != 0)
                    {
                    for (int i = 0; i < count; i++)
                    {
                    WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
                    current += dataSize;

                    ret.Add(si.SessionID + " " + si.State + " " + si.pWinStationName);
                    }

                    WTSFreeMemory(ppSessionInfo);
                    }
                    }
                    finally
                    {
                    CloseServer(server);
                    }

                    return ret;
                    }
                    }
                    }






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Sep 25 '08 at 11:23









                    Nescio

                    22.4k104669




                    22.4k104669












                    • This gives you some usefulinfo but not the usernames.
                      – James
                      Sep 25 '08 at 11:40










                    • How are we calling it?
                      – Si8
                      Apr 4 '17 at 15:30


















                    • This gives you some usefulinfo but not the usernames.
                      – James
                      Sep 25 '08 at 11:40










                    • How are we calling it?
                      – Si8
                      Apr 4 '17 at 15:30
















                    This gives you some usefulinfo but not the usernames.
                    – James
                    Sep 25 '08 at 11:40




                    This gives you some usefulinfo but not the usernames.
                    – James
                    Sep 25 '08 at 11:40












                    How are we calling it?
                    – Si8
                    Apr 4 '17 at 15:30




                    How are we calling it?
                    – Si8
                    Apr 4 '17 at 15:30


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f132620%2fhow-do-you-retrieve-a-list-of-logged-in-connected-users-in-net%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Create new schema in PostgreSQL using DBeaver

                    Deepest pit of an array with Javascript: test on Codility

                    Costa Masnaga