我正在使用C#.NET 2005编写Windows服务。如何确定当前登录用户(如果有)?还有一种方法可以在用户登录时收到通知吗?
或者,有没有办法知道谁最近使用过这台机器?
我需要知道当前登录的用户,以便我可以为该用户缓存一些数据。在企业环境中运行有数千个潜在用户,但只有使用该计算机的人缓存数据才有意义。
更新:
This solution效果很好。另请参阅this pinvoke.net example,它使用扩展结构来检索域名。
与此结合使用时,我使用SystemEvents类在用户登录计算机时收到通知。请参阅example 2 here以获取一个好例子 - 请注意,您需要使用服务中的隐藏表单才能使用服务中的SystemEvents。
答案 0 :(得分:3)
您可以使用P / Invoke来调用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;
}
}
答案 1 :(得分:0)
如您所知,Windows服务中可能没有当前登录的用户。为什么不在计算机上的启动登录过程中添加一个小的实用程序,只要有人登录就会运行,这将执行一个调用服务中数据缓存功能的方法。这样,该实用程序就可以访问登录用户的窗口原则身份。