c# - 如何从Windows服务确定当前的Windows用户?

标签 c# .net windows-services

我正在使用 C# .NET 2005 编写 Windows 服务。如何确定当前登录用户是谁(如果有)?还有一种方法可以在用户登录时收到通知?

或者,有没有办法知道谁最近使用过该机器?

我需要知道当前登录的用户,以便我可以缓存该用户的一些数据。在企业环境中运行有成千上万的潜在用户,但只有为使用该计算机的人缓存数据才有意义。

更新:

This solution效果很好。另请参阅this pinvoke.net example它使用扩展结构来检索域名。

与此相结合,我使用 SystemEvents 类在用户登录到计算机时收到通知。请参阅example 2 here举一个很好的例子 - 请注意,您需要使用服务中的隐藏表单才能使用服务中的 SystemEvents。

最佳答案

您可以使用P/Invoke调用NetWkstaUserEnum ,它将枚举当前登录的用户。请记住,如果存在终端服务器 session ,可能会有多个用户,并且并非所有返回的用户都是“真实”用户。正如文档所述:

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

以下是关于如何调用 NetWkstaUserEnum 的 C# 完整工作代码示例:

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

关于c# - 如何从Windows服务确定当前的Windows用户?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2077958/

相关文章:

c# - costura.fody 用于引用另一个 dll 的 dll

c# - 拦截包含 NHibernate 生成的参数值的 SQL 语句

c# - 如何在 Windows 上运行的自托管 ServiceStack 中获取用户名

c# - 将选项卡添加到图像文件的默认属性窗口

c# - 在 Simple Injector 中注册时设置收集项目的 Lifestyle

c# - .NET 3.5 版和 .NET 3.5 版客户端配置文件有什么区别

windows - 如何通过批处理文件检查服务是否正在运行并启动它,如果它没有运行?

c# - 如何将 Windows 服务安装到另一个系统?

c# - 如何在控制台服务主机中包含 WCF 自定义 header

c# - 无法在c#中的文本框中输入负数