[英]How to get current windows username from windows service in multiuser environment using .NET
我有一个Windows服务,该服务始终为所有登录的用户运行WPF应用程序,并且运行良好,现在在WPF应用程序中,我无法获得当前的用户名Environment.UserName; 返回“ SYSTEM”,这是可以理解的。 所以我想是找到可以由Process.GetCurrentProcess()。SessionId检索的当前进程的会话ID,然后获取所有登录到计算机并循环遍历的用户的列表,以查找与进程会话匹配的会话ID id和后来的用户名。
但是我不知道如何获取所有已登录用户的列表,或者如果有人可以帮助我,我将不胜感激。
在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)上不起作用,因为Microsoft似乎已删除了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;
}
您可以尝试使用此Code Spinet。 每当用户登录Windows时,“用户名”属性将包含该用户的用户名。 如果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());
}
我进行了一些搜索,找到了适合您的代码:
它将获取正在运行该进程的用户名...
参考: 如何确定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";
}
您可以尝试以下代码:
string username = "SYSTEM";
var explorer = Process.GetProcessesByName("explorer").FirstOrDefault();
if (explorer != null)
{
username = GetUsername(explorer.SessionId);
}
此处的GetUsername方法的实现: https ://stackoverflow.com/a/35810391/10412686
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.