J'ai un service Windows qui doit accéder aux ruches de registre sous HKEY_USERS lorsque les utilisateurs se connectent, soit localement, soit via Terminal Server. J'utilise une requête WMI sur win32_logonsession pour recevoir des événements lorsque les utilisateurs se connectent, et l'une des propriétés que je reçois de cette requête est un LogonId. Pour déterminer quelle ruche de registre j'ai besoin d'accéder, maintenant, j'ai besoin du SID des utilisateurs, qui est utilisé comme un nom de clé de registre sous HKEY_USERS.Obtenir le SID utilisateur à partir de l'ID de connexion (Windows XP et versions ultérieures)
Dans la plupart des cas, je peux obtenir cela en faisant un RelatedObjectQuery comme si (en C#):
RelatedObjectQuery relatedQuery = new RelatedObjectQuery("associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent");
où "LogonID" est la session d'ouverture de session ID de la requête de session. L'exécution de RelatedObjectQuery me donne généralement une propriété SID qui contient exactement ce dont j'ai besoin.
J'ai deux problèmes avec cela. Tout d'abord, LinkedObjectQuery ne renvoie aucun résultat pour un utilisateur de domaine qui se connecte avec des informations d'identification mises en cache, déconnecté du domaine. Deuxièmement, je ne suis pas satisfait de la performance de cette RelatedObjectQuery --- cela peut prendre plusieurs secondes à exécuter.
Voici un programme de ligne de commande rapide et corrompu que j'ai lancé ensemble pour expérimenter les requêtes. Plutôt que de mettre en place pour recevoir les événements, ce que les utilisateurs énumère sur la machine locale:
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);
}
}
}
}
Alors ... est-il moyen d'obtenir rapidement et de manière fiable le SID utilisateur donné les informations que je récupère de WMI, ou devrais Je cherche à utiliser quelque chose comme SENS à la place?
double possible de [Convertir un nom d'utilisateur pour une chaîne SID en C# /. NET] (http://stackoverflow.com/questions/1040623/convert-a-username-to-a-sid-string- in-c-net) – Richard