[英]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.