我有一个需要获取当前登录用户名的Windows服务。我尝试过使用System.Environment.UserName
、Windows身份验证和Windows表单身份验证,但是所有方法都返回“System”,因为我的服务在具有系统特权的用户下运行。有没有一种不需要更改我的服务帐户类型就可以获取当前登录用户名的方法?
我有一个需要获取当前登录用户名的Windows服务。我尝试过使用System.Environment.UserName
、Windows身份验证和Windows表单身份验证,但是所有方法都返回“System”,因为我的服务在具有系统特权的用户下运行。有没有一种不需要更改我的服务帐户类型就可以获取当前登录用户名的方法?
这是一个用于获取用户名的WMI查询:
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem");
ManagementObjectCollection collection = searcher.Get();
string username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
你需要手动在引用中添加 System.Management
。
Environment.UserName
将显示格式更改为:“用户名”,而不是
System.Security.Principal.WindowsIdentity.GetCurrent().Name
将显示格式:'网络名称\用户名'
选择您想要的格式。
ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem")的解决方案对我很有效。但如果服务是通过远程桌面连接启动的,则无法正常工作。 为了解决这个问题,我们可以请求交互式进程所有者的用户名,该进程始终在PC上运行:explorer.exe。这样,我们始终可以从我们的Windows服务中获取当前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;
}
}
修改自Tapas的回答的代码:
Dim searcher As New ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem")
Dim collection As ManagementObjectCollection = searcher.[Get]()
Dim username As String
For Each oReturn As ManagementObject In collection
username = oReturn("UserName")
Next
如果有人像我一样在寻找用户的显示名称而不是用户名,请注意以下内容:
这是解决方法:
System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName.
在您的项目中添加对System.DirectoryServices.AccountManagement
的引用。
System.Environment.GetEnvironmentVariable("UserName");
尝试使用 WindowsIdentity.GetCurrent()
。您需要添加对 System.Security.Principal
的引用。
补充来自@xanblax的答案
private static string getUserName()
{
SelectQuery query = new SelectQuery(@"Select * from Win32_Process");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
foreach (System.Management.ManagementObject Process in searcher.Get())
{
if (Process["ExecutablePath"] != null && string.Equals(Path.GetFileName(Process["ExecutablePath"].ToString()), "explorer.exe", StringComparison.OrdinalIgnoreCase))
{
string[] OwnerInfo = new string[2];
Process.InvokeMethod("GetOwner", (object[])OwnerInfo);
return OwnerInfo[0];
}
}
}
return "";
}
你可以通过当前登录用户的sessionId
来获取它。首先,你需要在你的代码类中添加以下的P/INVOKE
脚本:
[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,
}
[DllImport("Kernel32.dll", SetLastError = true)]
static extern int WTSGetActiveConsoleSessionId();
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;
}
int sessionId = WTSGetActiveConsoleSessionId();
string username = GetUsername(sessionId); // Gives 'Domain\Username'
来源链接: