我有一个Windows服务,它运行一个WPF应用程序所有的login用户,工作正常,现在在WPF应用程序,我不能得到一个当前的用户名为Environment.UserName; 返回'SYSTEM'这是可以理解的。 所以我认为find当前进程的会话ID,可以通过Process.GetCurrentProcess()。SessionId获取,然后获取所有login到机器的用户列表,并循环查找与进程会话匹配的会话ID身份证,后来他的用户名。
但我不怎么得到所有login用户的名单,或者如果有人可以帮助我的替代品,我将不胜感激。
在MSDN论坛上找到这个解决方案:
using System.Security.Principal; . . . WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent()); String username = wp.Identity.Name;
现在通过创建一个新的控制台应用程序,粘贴上面的代码,并将用户名字符串写入控制台,可以很容易地进行测试。 似乎工作正常,但对于服务显然是一个更复杂的情况。 由于所有的服务都在SYSTEM用户下运行的容器中运行,这就是他们返回的结果。 欲了解更多信息,请参阅下面的链接,特别是。 所有哈里朱的答案。
这似乎是不可能实现你想要得到的,因为服务完全与用户会话分离。
我通过在我的WPF应用程序执行powershell命令“quser”来解决这个问题,该应用程序返回所有登录的用户,然后我迭代查找会话ID,在该会话中应用程序正在用用户会话ID运行,然后检索他的名字。 下面是通过传递他的会话ID获取用户名的函数
private string GetUserName(int SessionId) { try { Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript("Quser"); pipeline.Commands.Add("Out-String"); Collection<PSObject> results = pipeline.Invoke(); runspace.Close(); StringBuilder stringBuilder = new StringBuilder(); foreach (PSObject obj in results) { stringBuilder.AppendLine(obj.ToString()); } foreach (string User in stringBuilder.ToString().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Skip(1)) { string[] UserAttributes = User.Split(new string[]{" "},StringSplitOptions.RemoveEmptyEntries); if (int.Parse(UserAttributes[2].Trim()) == SessionId) { return UserAttributes[0].Replace(">", string.Empty).Trim(); } } return stringBuilder.ToString(); } catch (Exception ex) { } return string.Empty; }
该函数可以被调用
string CurrentUser = GetUserName(Process.GetCurrentProcess().SessionId);
我在构建Windows服务时遇到了类似的问题。 就像你一样,我有会话ID,需要获得相应的用户名。 上面的Syed的答案在我的机器(Windows 10)上不起作用,因为微软似乎已经删除了quser
可执行文件。 经过几次不成功的解决方案后,我遇到了这个特殊的答案 ,它激发了我的解决方案:
这里是我的代码(所有这些都驻留在一个类中;在我的情况下,这个类继承了ServiceBase
)
[DllImport("Wtsapi32.dll")] private static extern bool WTSQuerySessionInformation(IntPtr hserver, int sessionId, WtsInfoClass wtsInfoClass, out IntPtr ppBuffer, out int pBytesReturned); [DllImport("Wtsapi32.dll")] private static extern void WTSFreeMemory(IntPtr pointer); private enum WtsInfoClass { WTSUserName = 5, WTSDomainName = 7, } private static string GetUsername(int sessionId, bool prependDomain = true) { IntPtr buffer; int strLen; string username = "SYSTEM"; if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSUserName, out buffer, out strLen) && strLen > 1) { username = Marshal.PtrToStringAnsi(buffer); WTSFreeMemory(buffer); if (prependDomain) { if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1) { username = Marshal.PtrToStringAnsi(buffer) + "\\" + username; WTSFreeMemory(buffer); } } } return username; }
我做了一个小小的搜索,找到了适合你的代码:
它会得到正在运行该进程的用户名…
参考: 如何确定C#中的进程的所有者?
public string GetProcessOwner(string processName) { string query = "Select * from Win32_Process Where Name = \"" + processName + "\""; ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); ManagementObjectCollection processList = searcher.Get(); foreach (ManagementObject obj in processList) { string[] argList = new string[] { string.Empty, string.Empty }; int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList)); if (returnVal == 0) { // return DOMAIN\user string owner = argList[1] + "\\" + argList[0]; return owner; } } return "NO OWNER"; }
你可以试试这个代码spinet。 每当用户登录到窗口,用户名属性将包含用户的用户名。 在windows系统中没有用户的情况下,将不会有Win32_ComputerSystem类的实例。
ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2"); ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_ComputerSystem"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, query); foreach(ManagementObject mo in searcher.Get()) { Console.WriteLine(mo["UserName"].ToString()); }