-2

My Problem:

I am developing a Standalone Console Application that has to find the currently logged-on active Windows Username.

Test Cases:

  1. Multiple Users logged on and only one user active.

  2. One user currently active, accessing other remote user also

  3. Others users in remote user same user that is currently active.

The order of signing in may vary, but in all cases only the current active user is required.

I've found these codes for the above mentioned task:

string UserName1 = System.Security.Principal.WindowsIdentity.GetCurrent().Name; // Gives NT AUTHORITY\SYSTEM
string UserName2 = Request.LogonUserIdentity.Name; // Gives NT AUTHORITY\SYSTEM
string UserName3 = Environment.UserName; // Gives SYSTEM
string UserName4 = HttpContext.Current.User.Identity.Name; // Gives actual user logged on (as seen in <ASP:Login />)
string UserName5 = System.Windows.Forms.SystemInformation.UserName; // Gives SYSTEM
string DisplayName = System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName

I know HttpContext is not purely console based, but if it satisfies the condition and comparable I will use it.

I don't know all the possible test cases and not able to test them.

I'm not sure which one will suit all my test cases.

I will accept any solution that will suit the needs.

Help me find the possible way.

Sorry for any mistakes and thanks for the help.

Karthik
  • 31
  • 1
  • 1
  • 7
  • Multiple users logged on and only one user active, logged on not means active? or they already logged out? Not really understand what is your question – Raynoceros Oct 31 '19 at 06:51
  • @Raynoceros Assume I have 2 Users A and B, 1st log on to User A then Switch User to B, Still Applications of User A is running, but now I want User B as it is the active one. If I swich back to User A while B is running also, I want A now – Karthik Oct 31 '19 at 06:55
  • Is this some sort of test question or assignment? If you want to find the current active user, first we must understand how your login code works. Show the code of your login part then we can help you. – Raynoceros Oct 31 '19 at 07:02
  • And you mention when you switch back from B to A and you want A, the code of switching parts is the key to your answer already. – Raynoceros Oct 31 '19 at 07:04
  • I see the confusion, the users are windows users, not the users of my application – Karthik Oct 31 '19 at 07:14
  • You are mixing technologies, at least from your problem statement. HttpContext is not available in a pure console application. You should have a look at: https://stackoverflow.com/questions/22609200/how-to-get-list-of-all-logged-in-users-using. That is old, so there might be a newer version of that API. – fredrik Oct 31 '19 at 07:15
  • [Here](https://www.google.com/search?q=windows+c%23+list+logged+in+users&rlz=1C1GCEB_enSE865SE865&oq=windows+C%23+list+logged+in+&aqs=chrome.2.69i57j33l2.6813j0j7&sourceid=chrome&ie=UTF-8) is a list of solutions that might be more up to date. – fredrik Oct 31 '19 at 07:20
  • Hope the following link can help you https://stackoverflow.com/questions/1240373/ – Niloofar Taati Oct 31 '19 at 07:45
  • Have you seen [1240373] (https://stackoverflow.com/questions/1240373)? maby it can heps you! – Niloofar Taati Oct 31 '19 at 09:45

1 Answers1

0

I've converted a C code to C# and implemented it.

public static class UserInfo
    {
        #region PInvoke

        [DllImport("wtsapi32.dll", SetLastError = true)]
        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
        }

        [DllImport("Wtsapi32.dll")]
        public static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTSInfoClass wtsInfoClass, out IntPtr ppBuffer, out uint pBytesReturned);

        public enum WTSInfoClass
        {
            WTSInitialProgram,
            WTSApplicationName,
            WTSWorkingDirectory,
            WTSOEMId,
            WTSSessionId,
            WTSUserName,
            WTSWinStationName,
            WTSDomainName,
            WTSConnectState,
            WTSClientBuildNumber,
            WTSClientName,
            WTSClientDirectory,
            WTSClientProductId,
            WTSClientHardwareId,
            WTSClientAddress,
            WTSClientDisplay,
            WTSClientProtocolType,
            WTSIdleTime,
            WTSLogonTime,
            WTSIncomingBytes,
            WTSOutgoingBytes,
            WTSIncomingFrames,
            WTSOutgoingFrames,
            WTSClientInfo,
            WTSSessionInfo
        }

        [Flags]
        public enum LocalMemoryFlags
        {
            LMEM_FIXED = 0x0000,
            LMEM_MOVEABLE = 0x0002,
            LMEM_NOCOMPACT = 0x0010,
            LMEM_NODISCARD = 0x0020,
            LMEM_ZEROINIT = 0x0040,
            LMEM_MODIFY = 0x0080,
            LMEM_DISCARDABLE = 0x0F00,
            LMEM_VALID_FLAGS = 0x0F72,
            LMEM_INVALID_HANDLE = 0x8000,
            LHND = (LMEM_MOVEABLE | LMEM_ZEROINIT),
            LPTR = (LMEM_FIXED | LMEM_ZEROINIT),
            NONZEROLHND = (LMEM_MOVEABLE),
            NONZEROLPTR = (LMEM_FIXED)
        }

        [DllImport("kernel32.dll")]
        static extern IntPtr LocalAlloc(uint uFlags, UIntPtr uBytes);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr LocalFree(IntPtr hMem);

        [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
        public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

        #endregion PInvoke

        #region Helper Methods

        public static bool GetPhysicallyLoggedOnUserName(out string PhysicallyLoggedOnUserName, out string DomainName)
        {
            PhysicallyLoggedOnUserName = string.Empty;
            DomainName = string.Empty;
            IntPtr WTS_CURRENT_SERVER_HANDLE = (IntPtr)null;
            try
            {
                IntPtr ppSessionInfo = IntPtr.Zero;
                Int32 pCount = 0;
                Int32 retval = WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref ppSessionInfo, ref pCount);
                Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
                if (retval != 0)
                {
                    Int64 current = (int)ppSessionInfo;
                    int totalactiveuser = 0;
                    for (int i = 0; i < pCount; i++)
                    {
                        WTS_SESSION_INFO wts = (WTS_SESSION_INFO)Marshal.PtrToStructure((IntPtr)current, typeof(WTS_SESSION_INFO));
                        current += dataSize;
                        if (wts.State == WTS_CONNECTSTATE_CLASS.WTSActive)
                        {
                            totalactiveuser++;
                        }
                    }

                    if (totalactiveuser < 1)
                    {
                        return false;
                    }

                    current = (int)ppSessionInfo;
                    for (int i = 0; i < pCount; i++)
                    {
                        WTS_SESSION_INFO wts = (WTS_SESSION_INFO)Marshal.PtrToStructure((IntPtr)current, typeof(WTS_SESSION_INFO));
                        current += dataSize;
                        if (wts.State != WTS_CONNECTSTATE_CLASS.WTSActive)
                        {
                            continue;
                        }

                        IntPtr szUserName = IntPtr.Zero;
                        uint dwLen = 0;
                        bool bStatus = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wts.SessionID, WTSInfoClass.WTSUserName, out szUserName, out dwLen);
                        if (bStatus)
                        {
                            IntPtr szUpn = LocalAlloc((uint)LocalMemoryFlags.LMEM_FIXED, new UIntPtr(unchecked((uint)szUserName.ToInt32())));
                            CopyMemory(szUpn, szUserName, (uint)IntPtr.Size);
                            LocalFree(szUpn);
                        }

                        IntPtr ProtoType = IntPtr.Zero;
                        bStatus = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wts.SessionID, WTSInfoClass.WTSClientProtocolType, out ProtoType, out dwLen);
                        int cpt = Marshal.ReadInt32(ProtoType);
                        WTSFreeMemory(ProtoType);
                        if (cpt == 0)   // WTS_PROTOCOL_TYPE_CONSOLE
                        {
                            PhysicallyLoggedOnUserName = Marshal.PtrToStringAnsi(szUserName);
                            WTSFreeMemory(szUserName);
                            dwLen = 0;
                            IntPtr szDomainName = IntPtr.Zero;
                            bStatus = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wts.SessionID, WTSInfoClass.WTSDomainName, out szDomainName, out dwLen);
                            DomainName = Marshal.PtrToStringAnsi(szDomainName);
                            WTSFreeMemory(szDomainName);
                            return true;
                        }

                        WTSFreeMemory(szUserName);
                    }
                }
            }
            catch
            {
                return false;
            }

            return false;
        }

        #endregion Helper Methods
    }
Karthik
  • 31
  • 1
  • 1
  • 7