简体   繁体   English

如何从Windows服务确定当前Windows用户?

[英]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)? 我正在使用C#.NET 2005编写Windows服务。如何确定当前登录的用户是谁(如果有)? 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. 另请参见此pinvoke.net示例该示例使用扩展结构还检索域名。

In combination with this I'm using the SystemEvents class to be notified when a user logs on to the machine. 与此结合,我使用SystemEvents类在用户登录计算机时得到通知。 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. 请参见此处的示例2,这是一个很好的示例-请注意,您需要使用服务中的隐藏表单才能使用服务中的SystemEvents。

You can use P/Invoke to call NetWkstaUserEnum , which will enumerate the currently logged on users. 您可以使用P / Invoke调用NetWkstaUserEnum ,它将枚举当前登录的用户。 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: 这是C#中有关如何调用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. 如您所知,Windows服务中可能没有当前登录的用户。 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. 为什么不将一个小的实用程序添加到计算机上的启动登录过程中,该程序将在有人登录时运行,该程序将执行一种方法,该方法调用服务中的数据缓存功能。这样,该实用程序将可以访问登录用户的Windows原理身份。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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