如何在.NET中从Windows服务中获取当前登录的用户名?
问题的原因是,在使用ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem")获取当前登录的用户名时,如果服务是通过远程桌面连接启动的,这种方法将不起作用。为了解决这个问题,可以通过获取一个始终在计算机上运行的交互式进程(explorer.exe)的所有者用户名来获取当前登录的Windows用户名。
解决方法如下:
foreach (System.Management.ManagementObject Process in Processes.Get()) { if (Process["ExecutablePath"] != null && System.IO.Path.GetFileName(Process["ExecutablePath"].ToString()).ToLower() == "explorer.exe" ) { string[] OwnerInfo = new string[2]; Process.InvokeMethod("GetOwner", (object[])OwnerInfo); Console.WriteLine(string.Format("Windows Logged-in Interactive UserName={0}", OwnerInfo[0])); break; } }
但是,如果同时有多个用户登录(例如,在Windows 10中切换到另一个用户),这种方法将不起作用,因为每个用户都会运行一个explorer.exe实例。为了解决这个问题,可以使用以下代码来获取explorer.exe的正确副本:
ManagementObjectSearcher Processes = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Process");
为了确保获取到正确的explorer.exe副本,可以获取当前进程的会话ID,并将其与找到的explorer.exe的SessionID属性值进行比较,然后从该explorer.exe中获取用户信息。
当然,一个Windows服务可能在没有UI或没有在其会话中运行explorer.exe的情况下运行,所以你可能需要采取其他方法。但是,在Windows桌面应用程序中使用这种方法效果很好。
问题的出现原因:\n用户在Windows服务中想要获取当前登录的用户名,但是通常的获取用户名的方法在运行服务时不起作用,因为存在系统账户的问题。\n解决方法:\n通过使用WMI查询来获取用户名。需要手动添加对System.Management的引用。以下是获取用户名的代码示例:\n
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem"); ManagementObjectCollection collection = searcher.Get(); string username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
\n这个解决方法适用于在Windows 10 20H2的系统账户下运行的服务应用程序。\n需要注意的是,这个WMI查询在远程(RDP)会话中不起作用。如果其他人在将来阅读这篇文章时,要让他们更容易看到这个注意事项。