Как я могу получить текущее имя пользователя из службы Windows в.NET?
У меня есть служба Windows, которая требует текущего имени пользователя. Я старался System.Environment.UserName
, Удостоверение Windows и проверка подлинности Windows Form, но все возвращают "System" как пользователь, поскольку моя служба работает в привилегированном режиме. Есть ли способ получить имя пользователя, вошедшего в систему, без изменения типа учетной записи моей службы?
9 ответов
Это запрос 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") работало нормально для меня. НО это не работает, если служба запущена через подключение к удаленному рабочему столу. Чтобы обойти это, мы можем запросить имя пользователя владельца интерактивного процесса, который всегда выполняется на ПК: 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;
}
}
Модифицированный код ответа Тапаса:
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
Пытаться WindowsIdentity.GetCurrent()
, Вам нужно добавить ссылку на System.Security.Principal
Вы также можете попробовать
System.Environment.GetEnvironmentVariable("UserName");
На всякий случай, если кто-то ищет отображаемое имя пользователя, а не имя пользователя, как я.
Вот угощение:
System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName.
Добавить ссылку на System.DirectoryServices.AccountManagement
в вашем проекте.
Завершение ответа от @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 "";
}
Ответ для службы Windows:
Вы можете получить его из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'
Ссылки на источники: