我有一個Windows服務,需要在用戶登錄時訪問HKEY_USERS下的註冊表配置單元,無論是本地還是通過終端服務器。我在win32_logonsession上使用WMI查詢來接收用戶登錄時的事件,並且從該查詢中獲得的其中一個屬性是LogonId。爲了找出我需要訪問哪個註冊表配置單元,現在我需要用戶的SID,它用作HKEY_USERS下的註冊表項名稱。從登錄ID(Windows XP和更高版本)獲取用戶SID
在大多數情況下,我可以做一個RelatedObjectQuery像這樣(在C#)得到這樣的:
RelatedObjectQuery relatedQuery = new RelatedObjectQuery("associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent");
其中「LogonID的」是從會話查詢登錄會話ID。運行RelatedObjectQuery通常會給我一個SID屬性,其中包含我所需要的。
我對此有兩個問題。首先也是最重要的一點,相關對象查詢不會爲使用與域斷開連接的緩存憑證登錄的域用戶返回任何結果。其次,我對這個相關對象查詢的性能不滿意 - 它可能需要幾秒鐘才能執行。
這裏是一個快速而骯髒的命令行程序,我扔在一起實驗查詢。而不是設置爲接收事件,這只是列舉了在本地計算機上的用戶:
using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
namespace EnumUsersTest
{
class Program
{
static void Main(string[] args)
{
ManagementScope scope = new ManagementScope("\\\\.\\root\\cimv2");
string queryString = "select * from win32_logonsession"; // for all sessions
//string queryString = "select * from win32_logonsession where logontype = 2"; // for local interactive sessions only
ManagementObjectSearcher sessionQuery = new ManagementObjectSearcher(scope, new SelectQuery(queryString));
ManagementObjectCollection logonSessions = sessionQuery.Get();
foreach (ManagementObject logonSession in logonSessions)
{
string logonID = logonSession["LogonId"].ToString();
Console.WriteLine("=== {0}, type {1} ===", logonID, logonSession["LogonType"].ToString());
RelatedObjectQuery relatedQuery = new RelatedObjectQuery("associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent");
ManagementObjectSearcher userQuery = new ManagementObjectSearcher(scope, relatedQuery);
ManagementObjectCollection users = userQuery.Get();
foreach (ManagementObject user in users)
{
PrintProperties(user.Properties);
}
}
Console.WriteLine("\nDone! Press a key to exit...");
Console.ReadKey(true);
}
private static void PrintProperty(PropertyData pd)
{
string value = "null";
string valueType = "n/a";
if (pd.Value != null)
{
value = pd.Value.ToString();
valueType = pd.Value.GetType().ToString();
}
Console.WriteLine(" \"{0}\" = ({1}) \"{2}\"", pd.Name, valueType, value);
}
private static void PrintProperties(PropertyDataCollection properties)
{
foreach (PropertyData pd in properties)
{
PrintProperty(pd);
}
}
}
}
所以...有沒有辦法快速,可靠地獲取給定的,我從WMI檢索信息的用戶的SID,還是應該我正在尋找使用像SENS而不是?
可能重複的[轉換用戶名到C#中的SID串/。NET](http://stackoverflow.com/questions/1040623/convert-a-username-to-a-sid-string- in-c-net) – Richard 2011-01-04 10:33:08