简体   繁体   中英

How to determine the current windows user from a windows service?

I'm writing a Windows Service using C# .NET 2005. How can I determine who the currently logged-on user is (if any)? Also is there a way to be notified when a user logs on?

Alternatively, is there a way to know who has recently used the machine?

I need to know the currently logged on user so I can cache some data for that user. Operating in a corporate environment there are thousands of potential users but it only makes sense to cache data for someone who uses that machine.

UPDATE:

This solution works well. Also see this pinvoke.net example which uses the extended structure to also retrieve domain name.

In combination with this I'm using the SystemEvents class to be notified when a user logs on to the machine. See example 2 here for a good example - note that you need to use a hidden form from a service in order to be able to use SystemEvents from a service.

You can use P/Invoke to call NetWkstaUserEnum , which will enumerate the currently logged on users. Keep in mind that there might be more than one user in case there are terminal server sessions, and that not all users returned is a "real" user. As the documentation states:

"This list includes interactive, service and batch logons."

Here is a complete working code example in C# on how to call NetWkstaUserEnum:

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

namespace EnumerateUsers
{
    class Program
    {
        static void Main(string[] args)
        {
            var ue = new UserEnumerator();
            foreach(string userName in ue.GetLoggedOnUsers(null))
            {
                Console.WriteLine(userName);
            }
        }

    }

    class UserEnumerator
    {
        public IEnumerable<string> GetLoggedOnUsers(string host)
        {
            int entriesRead, totalEntries, resumeHandle = 0;
            IntPtr pBuffer = IntPtr.Zero;
            try
            {
                int result = NetWkstaUserEnum(host, 0, out pBuffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, ref resumeHandle);
                if (result != NERR_Success)  
                    throw new ApplicationException(String.Format("Failed to enumerate users, error code {0}", result));

                return GetUsersFromStruct(pBuffer, entriesRead).ToList();
            }
            finally
            {
                if (pBuffer != IntPtr.Zero)
                    NetApiBufferFree(pBuffer);
                }

        }

        private IEnumerable<string> GetUsersFromStruct(IntPtr pBuffer, int count)
        {
            for (int i = 0; i < count; i++)
            {
                var user = (WKSTA_USER_INFO_0)Marshal.PtrToStructure(pBuffer, typeof(WKSTA_USER_INFO_0));
                yield return user.username;
                pBuffer = IntPtr.Add(pBuffer, user.username.Length * 2);                
            }
        }
        [DllImport("netapi32.dll")]
        private static extern int NetWkstaUserEnum(string host, int level, out IntPtr pBuffer, int prefMaxLength, out int entriesRead,
                                     out int totalEntries, ref int resumeHandle);

        [DllImport("netapi32.dll")]
        private static extern int NetApiBufferFree(IntPtr buffer);

        private const int MAX_PREFERRED_LENGTH = -1;

        private const int NERR_Success = 0;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct WKSTA_USER_INFO_0
    { 
        [MarshalAs(UnmanagedType.LPTStr)]
        internal string username;
    }
}

As you know, there may not be a currently logged on user within a Windows service. Why not not add a small utility program to the startup logon process on the machine, that will run whenever someone logs on, that will execute a method that calls the data caching functionality in the service.. That way that utility will have access to the logged on users' windows principle Identity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM