[英]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.